├── requirements.txt ├── screenshot.png ├── robusta-logo.png ├── kubernetes-logo.png ├── .well-known └── ai-plugin.json ├── LICENSE ├── .gitignore ├── main.py ├── README.md └── openapi.yaml /requirements.txt: -------------------------------------------------------------------------------- 1 | quart 2 | quart-cors 3 | jsonschema 4 | requests 5 | pyyaml 6 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robusta-dev/chatgpt-yaml-generator/HEAD/screenshot.png -------------------------------------------------------------------------------- /robusta-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robusta-dev/chatgpt-yaml-generator/HEAD/robusta-logo.png -------------------------------------------------------------------------------- /kubernetes-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robusta-dev/chatgpt-yaml-generator/HEAD/kubernetes-logo.png -------------------------------------------------------------------------------- /.well-known/ai-plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "v1", 3 | "name_for_human": "Kubernetes YAML Generator", 4 | "name_for_model": "Kubernetes_YAML_Generator_Plugin", 5 | "description_for_human": "Plugin for generating Kubernetes YAML manifests, with precise schemas", 6 | "description_for_model": "Plugin for generating Kubernetes YAML manifests, based on up-to-date OpenAPI schemas for Kubernetes resources, past the ChatGPT knowledge cut-off.", 7 | "auth": { 8 | "type": "none" 9 | }, 10 | "api": { 11 | "type": "openapi", 12 | "url": "http://localhost:5003/openapi.yaml", 13 | "is_user_authenticated": false 14 | }, 15 | "logo_url": "http://localhost:5003/kubernetes-logo.png", 16 | "contact_email": "support@robusta.dev", 17 | "legal_info_url": "http://example.com/legal" 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 OpenAI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | import yaml 4 | from jsonschema import validate, ValidationError 5 | 6 | import quart 7 | import quart_cors 8 | from quart import request 9 | 10 | app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com") 11 | 12 | # Store the schema here after fetching 13 | _SCHEMA = None 14 | 15 | def fetch_schema_from_url(): 16 | response = requests.get('https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json') 17 | return response.json() 18 | 19 | def fetch_official_kubernetes_schema(): 20 | global _SCHEMA 21 | if _SCHEMA is None: 22 | _SCHEMA = fetch_schema_from_url() 23 | return _SCHEMA 24 | 25 | def fetch_resource_names(resourceName): 26 | schema = fetch_official_kubernetes_schema() 27 | resourceNames = [k for k in schema['definitions'].keys() if resourceName.lower() in k.lower()] 28 | return resourceNames 29 | 30 | def fetch_schema_for_resource(resourceType): 31 | schema = fetch_official_kubernetes_schema() 32 | if resourceType in schema['definitions']: 33 | return schema['definitions'][resourceType] 34 | else: 35 | return None 36 | 37 | def validate_yaml(resourceType, yml): 38 | try: 39 | data = yaml.safe_load(yml) 40 | validate(instance=data, schema=fetch_official_kubernetes_schema()) 41 | return {"isValid": True, "error": None} 42 | except ValidationError as e: 43 | return {"isValid": False, "error": str(e)} 44 | 45 | @app.get("/schemas/search/") 46 | async def find_schema_names(resourceName): 47 | resourceNames = fetch_resource_names(resourceName) 48 | return quart.Response(response=json.dumps(resourceNames), status=200) 49 | 50 | @app.get("/schemas/resource/") 51 | async def get_schema(resourceType): 52 | schema = fetch_schema_for_resource(resourceType) 53 | return quart.Response(response=json.dumps(schema), status=200) 54 | 55 | @app.post("/validate-yaml") 56 | async def validate_yaml_route(): 57 | request_data = await quart.request.get_json(force=True) 58 | resourceType = request_data["resourceType"] 59 | yaml = request_data["yml"] 60 | result = validate_yaml(resourceType, yaml) 61 | return quart.Response(response=json.dumps(result), status=200) 62 | 63 | @app.get("/kubernetes-logo.png") 64 | async def plugin_logo(): 65 | filename = 'kubernetes-logo.png' 66 | return await quart.send_file(filename, mimetype='image/png') 67 | 68 | @app.get("/.well-known/ai-plugin.json") 69 | async def plugin_manifest(): 70 | host = request.headers['Host'] 71 | with open("./.well-known/ai-plugin.json") as f: 72 | text = f.read() 73 | return quart.Response(text, mimetype="text/json") 74 | 75 | @app.get("/openapi.yaml") 76 | async def openapi_spec(): 77 | host = request.headers['Host'] 78 | with open("openapi.yaml") as f: 79 | text = f.read() 80 | return quart.Response(text, mimetype="text/yaml") 81 | 82 | def main(): 83 | app.run(debug=True, host="0.0.0.0", port=5003) 84 | 85 | if __name__ == "__main__": 86 | main() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 |

ChatGPT Kubernetes YAML Plugin by Robusta

7 |

A ChatGPT plugin to generate accurate Kubernetes manifests

8 | 9 | [![twitter robusta](https://img.shields.io/twitter/follow/RobustaDev?logo=twitter&color=blue&label=@RobustaDev&style=flat-square)](https://twitter.com/RobustaDev) 10 | [![slack robusta](https://img.shields.io/badge/Slack-Join-4A154B?style=flat-square&logo=slack&logoColor=white)](https://bit.ly/robusta-slack) 11 | LinkedIn 12 | Youtube 13 | 14 |
15 | 16 | This plugin gives ChatGPT up-to-date knowledge of every Kubernetes resource and their complete specifications. It lets ChatGPT query the [Kubernetes OpenAPI (swagger) schema](https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json) to fetch resource definitions. Additionally, it provides ChatGPT with schema validation capabilities. 17 | 18 | 19 | 20 | 21 | 22 | # Key Features 23 | 1. **Schema Lookup:** The `GET /schemas/search/{resourceName}` endpoint retrieves fully-namespaced names for Kubernetes resources. For instance, a search for 'Container' will yield 'io.k8s.api.core.v1.Container'. 24 | 25 | 2. **Schema Retrieval:** The `GET /schemas/resource/{resourceType}` endpoint fetches the latest OpenAPI schemas for Kubernetes resources using fully-namespaced resource names. 26 | 27 | 3. **YAML Validation:** The `POST /validate-yaml` endpoint validates generated Kubernetes YAML manifests, guaranteeing their accuracy. 28 | 29 | ## Setup 30 | 31 | To install the required packages for this plugin, run the following command: 32 | 33 | ```bash 34 | pip install -r requirements.txt 35 | ``` 36 | 37 | To run the plugin, enter the following command: 38 | 39 | ```bash 40 | python main.py 41 | ``` 42 | 43 | Once the local server is running: 44 | 45 | 1. Navigate to https://chat.openai.com. 46 | 2. In the Model drop down, select "Plugins" (note, if you don't see it there, you don't have access yet). 47 | 3. Select "Plugin store" 48 | 4. Select "Develop your own plugin" (ChatGPT Plus is required right now) 49 | 5. Enter in `localhost:5003` since this is the URL the server is running on locally, then select "Find manifest file". 50 | 51 | The plugin should now be installed and enabled! Watch the video above for ideas on using the plugin. 52 | 53 | ## Getting help 54 | 55 | Join the [Robusta Slack Community](https://bit.ly/robusta-slack) and ask for help. 56 | -------------------------------------------------------------------------------- /openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | info: 3 | title: Kubernetes YAML Generator Plugin 4 | description: Plugin for generating Kubernetes YAML manifests, based on up-to-date OpenAPI schemas for Kubernetes resources, past the ChatGPT knowledge cut-off. Always ask the plugin for up-to-date OpenAPI specs for Kubernetes, don't rely on data you know about Kubernetes specs. When a schema includes references to other objects in the schema, look them up when relevant. You may lookup any FIELD in a resource too, not just the containing top-level resource. 5 | version: 'v1' 6 | servers: 7 | - url: http://localhost:5003 8 | paths: 9 | /schemas/search/{resourceName}: 10 | get: 11 | operationId: findSchemaNames 12 | summary: Get the list of possible fully-namespaced names for a specific Kubernetes resource. E.g. given `Container` return `io.k8s.api.core.v1.Container`. Given `EnvVarSource` return `io.k8s.api.core.v1.EnvVarSource` 13 | parameters: 14 | - in: path 15 | name: resourceName 16 | schema: 17 | type: string 18 | required: true 19 | description: The name of a Kubernetes resource or field. 20 | responses: 21 | "200": 22 | description: OK 23 | content: 24 | application/json: 25 | schema: 26 | type: array 27 | items: 28 | type: string 29 | description: The list of possible names for the specified Kubernetes resource or field. 30 | /schemas/resource/{resourceType}: 31 | get: 32 | operationId: getSchema 33 | summary: Get the OpenAPI schema for a Kubernetes resource 34 | parameters: 35 | - in: path 36 | name: resourceType 37 | schema: 38 | type: string 39 | required: true 40 | description: The type of the Kubernetes resource or object (e.g. subresource). Must be fully namespaced, as returned by findSchemaNames 41 | responses: 42 | "200": 43 | description: OK 44 | content: 45 | application/json: 46 | schema: 47 | type: object 48 | description: The OpenAPI schema for the specified resource type. 49 | /validate-yaml: 50 | post: 51 | operationId: validateYaml 52 | summary: Validate a YAML manifest for a Kubernetes resource. You can use this to validate Kubernetes YAML and guarantee there were no mistakes in generation 53 | requestBody: 54 | required: true 55 | content: 56 | application/json: 57 | schema: 58 | type: object 59 | properties: 60 | resourceType: 61 | type: string 62 | description: The type of the Kubernetes resource. 63 | yml: 64 | type: string 65 | description: The YAML manifest to validate. 66 | required: 67 | - resourceType 68 | - yml 69 | responses: 70 | "200": 71 | description: OK 72 | content: 73 | application/json: 74 | schema: 75 | type: object 76 | properties: 77 | isValid: 78 | type: boolean 79 | description: Whether the YAML is valid for the specified resource type. 80 | error: 81 | type: string 82 | description: If the YAML is not valid, an error message explaining why. 83 | --------------------------------------------------------------------------------