{"id":17956486,"url":"https://github.com/looztra/kubesplit","last_synced_at":"2026-04-06T16:01:23.978Z","repository":{"id":34934416,"uuid":"172791587","full_name":"looztra/kubesplit","owner":"looztra","description":"Split multidoc yaml formatted kubernetes descriptors to a set of single resource files","archived":false,"fork":false,"pushed_at":"2025-03-26T03:10:52.000Z","size":326,"stargazers_count":45,"open_issues_count":3,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-30T08:11:16.650Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/looztra.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.rst","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-26T21:14:05.000Z","updated_at":"2025-03-24T08:02:36.000Z","dependencies_parsed_at":"2025-03-09T21:34:56.766Z","dependency_job_id":null,"html_url":"https://github.com/looztra/kubesplit","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/looztra%2Fkubesplit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/looztra%2Fkubesplit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/looztra%2Fkubesplit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/looztra%2Fkubesplit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/looztra","download_url":"https://codeload.github.com/looztra/kubesplit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247457803,"owners_count":20941906,"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-10-29T10:38:03.842Z","updated_at":"2026-04-06T16:01:23.971Z","avatar_url":"https://github.com/looztra.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kubesplit\n\n[![Pypi](https://img.shields.io/pypi/v/kubesplit.svg)](https://pypi.python.org/pypi/kubesplit)\n[![codecov](https://codecov.io/github/looztra/kubesplit/graph/badge.svg?token=ZK8IEI6VOS)](https://codecov.io/github/looztra/kubesplit)\n\n## What?\n\nSplit multidoc yaml formatted [kubernetes](https://kubernetes.io/) descriptors to a set of single resource files.\n\nIf you just want an opinionated yaml formatter, you can have a look at [yamkix](https://github.com/looztra/yamkix).\n\n## Installation\n\n### The pip way\n\n```bash\n# Install/Update\npip3 install -U --user kubesplit\n# Enjoy\nkubesplit -i path/to/yaml_file.yml -o path/to/output/directory\n# or\ncat path/to/yaml_file.yml | kubesplit -o path/to/output/directory\n\n```\n\n### The docker way\n\n```bash\n# Use latest\ndocker image pull looztra/kubesplit\n# Or one of the version+sha1 related tags\ndocker image pull looztra/kubesplit:[version]-[sha1]\n# Enjoy\ndocker container run \\\n        -ti --rm \\\n        -v $(pwd):/code \\\n        -w /code looztra/kubesplit \\\n        -i path/to/yaml_file.yml \\\n        -o path/to/output/directory\n# or\ncat path/to/yaml_file.yml | \\\n        docker container run \\\n        -ti --rm \\\n        -v $(pwd):/code \\\n        -w /code looztra/kubesplit \\\n        -o path/to/output/directory\n```\n\nAll tags available at \u003chttps://cloud.docker.com/repository/docker/looztra/kubesplit/tags\u003e\n\n## Usage\n\n```bash\n╰(.venv)─» kubesplit -h\nusage: kubesplit [-h] [-i INPUT] [-t TYP] -o OUTPUT_DIR [-n] [-e] [-q] [-f]\n        [-d] [-c] [-p]\n\nSplit a set of Kubernetes descriptors to a set of files. The yaml format of\nthe generated files can be tuned using the same parameters as the one used by\nYamkix. By default, explicit_start is `On`, explicit_end is `Off` and array\nelements are pushed inwards the start of the matching sequence. Comments are\npreserved thanks to default parsing mode `rt`.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -i INPUT, --input INPUT\n                        the file to parse, or STDIN if not specified or if\n                        value is -\n  -t TYP, --typ TYP     the yaml parser mode. Can be `safe` or `rt`\n  -o OUTPUT_DIR, --output-dir OUTPUT_DIR\n                        the name of the output target directory. The target\n                        directory will be created if it does not exist if it's\n                        possible\n  -n, --no-explicit-start\n                        by default, explicit start (---) of the yaml doc is\n                        `On`, you can disable it with this option\n  -e, --explicit-end    by default, explicit end (...) of the yaml doc is\n                        `Off`, you can enable it with this option\n  -q, --no-quotes-preserved\n                        by default, quotes are preserved you can disable this\n                        with this option\n  -f, --default-flow-style\n                        enable the default flow style `Off` by default. In\n                        default flow style (with typ=`rt`), maps and lists are\n                        written like json\n  -d, --no-dash-inwards\n                        by default, dash are pushed inwards use `--no-dash-\n                        inwards` to have the dash start at the sequence level\n  -c, --clean-output-dir\n                        clean the output directory (rmtree) if set (default is\n                        False)\n  -p, --no-resource-prefix\n                        by default, resource files are number prefixed, you\n                        can disable this behaviour with this flag\n\n```\n\n## Features\n\n- Invalid Kubernetes resources are ignored\n- Empty resources are ignored\n- Each resource found in the input is stored in a file with a name reflecting the name of the resource and its _kubernetes_ kind\n- Cluster-wide resources (namespaces, clusterroles, clusterrolebindings) are stored in the root directory of the output, namespaced resources are stored in a subdirectory named like the namespace\n- By default, resources are prefixed, use `--no-resource-prefix` to disable order prefixes\n- By default, quotes are preserved, use `--no-quotes-preserved` to disable quotes unless needed (for boolean and numbers if they were provided in the input as for the moment Kubesplit is not aware of the fact that only kubernetes annotations and environment variables require string)\n- By default, dash elements in list are pushed inwards, you can disable this behaviour with the `-d`/`--no-dash-inwards` option\n- Comments are preserved\n- The output directory will be created if it doesn't exist (if the user running the command as sufficient rights)\n- You can clean (delete files and directories existing before running `kubesplit`) the output directory with the `-c`/`--clean-output-dir` (**use at your own risks**)\n\n## Examples\n\nYou can find some input and output examples in the [test-assets](https://github.com/looztra/kubesplit/tree/master/test-assets) directory\n\n### Valid resources, no quotes preserved\n\n```bash\n╰(.venv)─»  kubesplit --input test-assets/source/all-in-one.yml \\\n              --output test-assets/expected/all-in-one--no-quotes-preserved \\\n              --no-quotes-preserved \\\n              --clean-output-dir\nProcessing: input=test-assets/source/all-in-one.yml, output_dir=test-assets/expected/all-in-one--no-quotes-preserved, clean_output_dir=True, typ=rt, explicit_start=True, explicit_end=False, default_flow_style=False, quotes_preserved=False, dash_inwards=True, prefix_resource_files=True\nFound [16] valid / [0] invalid / [0] empty resources\n\n╰(.venv)─» tree --dirsfirst test-assets/expected/all-in-one--no-quotes-preserved\ntest-assets/expected/all-in-one--no-quotes-preserved\n├── apps-demo\n│   └── 05--rolebinding--example-ns-demo-developer-binding.yml\n├── apps-integration\n│   └── 05--rolebinding--example-ns-integration-developer-binding.yml\n├── ingress-controllers\n│   ├── 03--serviceaccount--traefik-ingress-controller.yml\n│   ├── 11--configmap--traefik-conf.yml\n│   ├── 12--persistentvolumeclaim--traefik-acme.yml\n│   ├── 20--deployment--traefik-ingress-controller.yml\n│   ├── 30--service--traefik-ingress-endpoint.yml\n│   ├── 30--service--traefik-web-ui.yml\n│   └── 31--ingress--traefik-web-ui.yml\n├── 00--namespace--apps-demo.yml\n├── 00--namespace--apps-integration.yml\n├── 00--namespace--ingress-controllers.yml\n├── 01--clusterrole--example-node-viewer.yml\n├── 01--clusterrole--example-traefik-ingress-controller.yml\n├── 02--clusterrolebinding--example-node-viewer-developer.yml\n└── 02--clusterrolebinding--example-traefik-ingress-controller.yml\n\n3 directories, 16 files\n```\n\n### Valid resources, no prefix, no quotes preserved\n\n```bash\n╰(.venv)─» kubesplit --input test-assets/source/all-in-one.yml \\\n              --output test-assets/expected/all-in-one--no-quotes-preserved--no-resource-prefix \\\n              --no-quotes-preserved \\\n              --no-resource-prefix \\\n              --clean-output-dir\nProcessing: input=test-assets/source/all-in-one.yml, output_dir=test-assets/expected/all-in-one--no-quotes-preserved--no-resource-prefix, clean_output_dir=True, typ=rt, explicit_start=True, explicit_end=False, default_flow_style=False, quotes_preserved=False, dash_inwards=True, prefix_resource_files=False\nFound [16] valid / [0] invalid / [0] empty resources\n\n╰(.venv)─» tree --dirsfirst test-assets/expected/all-in-one--no-quotes-preserved--no-resource-prefix\ntest-assets/expected/all-in-one--no-quotes-preserved--no-resource-prefix\n├── apps-demo\n│   └── rolebinding--example-ns-demo-developer-binding.yml\n├── apps-integration\n│   └── rolebinding--example-ns-integration-developer-binding.yml\n├── ingress-controllers\n│   ├── configmap--traefik-conf.yml\n│   ├── deployment--traefik-ingress-controller.yml\n│   ├── ingress--traefik-web-ui.yml\n│   ├── persistentvolumeclaim--traefik-acme.yml\n│   ├── serviceaccount--traefik-ingress-controller.yml\n│   ├── service--traefik-ingress-endpoint.yml\n│   └── service--traefik-web-ui.yml\n├── clusterrolebinding--example-node-viewer-developer.yml\n├── clusterrolebinding--example-traefik-ingress-controller.yml\n├── clusterrole--example-node-viewer.yml\n├── clusterrole--example-traefik-ingress-controller.yml\n├── namespace--apps-demo.yml\n├── namespace--apps-integration.yml\n└── namespace--ingress-controllers.yml\n\n3 directories, 16 files\n```\n\n### Mixed content : valid, invalid and empty resources, no quotes preserved\n\n```bash\n╰(.venv)─» kubesplit --input test-assets/source/mixed-content-valid-invalid-and-empty-resources.yml \\\n                        --output test-assets/expected/mixed-content-valid-invalid-and-empty-resources--no-quotes-preserved \\\n                        --no-quotes-preserved \\\n                        --clean-output-dir\nProcessing: input=test-assets/source/mixed-content-valid-invalid-and-empty-resources.yml, output_dir=test-assets/expected/mixed-content-valid-invalid-and-empty-resources--no-quotes-preserved, clean_output_dir=True, typ=rt, explicit_start=True, explicit_end=False, default_flow_style=False, quotes_preserved=False, dash_inwards=True, prefix_resource_files=True\nFound [2] valid / [1] invalid / [1] empty resources\n\n╰(.venv)─» tree --dirsfirst test-assets/expected/mixed-content-valid-invalid-and-empty-resources--no-quotes-preserved\ntest-assets/expected/mixed-content-valid-invalid-and-empty-resources--no-quotes-preserved\n├── akira\n│   └── 25--replicaset--bididididi.yml\n└── yolo\n    └── 25--replicaset--frontend.yml\n\n2 directories, 2 files\n\n```\n\n## Use cases\n\n### With Kustomize\n\n```bash\nkustomize build overlays/prod | kubesplit -q -i - -o generated/prod\n\n```\n\n### With Helm\n\n```bash\nhelm template --namespace target-ns --values config.yml my-chart | kubesplit -q -i - -o generated/prod\n\n```\n\n## To preserve or not to preserve quotes?\n\n- _Quotes preserved_ means : if there were quotes in the input, they will also be present in the output, and it will be the same type (single/double) of quotes\n- _Quotes not preserved_ means :\n  - if quotes are not necessary (around _pure_ strings), they will be removed\n  - if quotes are present around booleans and numbers, they will be converted to default (single quotes)\n  - if quotes are not present around booleans and numbers, there will be no quotes in the output too\n\n**Note**: there is no option for the moment to force the usage of double quotes when `-q`/`--no-quotes-preserved` is used.\n\n### Quotes preserved (default behaviour)\n\nWith input :\n\n```yaml\n---\napiVersion: extensions/v1beta1 # with comment\nkind: ReplicaSet\nmetadata:\n  name: tname\n  namespace: tns\n  annotations:\n    string_no_quotes: frontend\n    string_single_quotes: 'frontend'\n    string_double_quotes: \"frontend\"\n    boolean_no_quotes: true\n    boolean_single_quotes: 'true'\n    boolean_double_quotes: \"true\"\n    number_no_quotes: 1\n    number_single_quotes: '1'\n    number_double_quotes: \"1\"\n```\n\nthe ouput will be the same as the input :\n\n```yaml\n---\napiVersion: extensions/v1beta1 # with comment\nkind: ReplicaSet\nmetadata:\n  name: tname\n  namespace: tns\n  annotations:\n    string_no_quotes: frontend\n    string_single_quotes: 'frontend'\n    string_double_quotes: \"frontend\"\n    boolean_no_quotes: true\n    boolean_single_quotes: 'true'\n    boolean_double_quotes: \"true\"\n    number_no_quotes: 1\n    number_single_quotes: '1'\n    number_double_quotes: \"1\"\n\n```\n\n### Quotes not preserved (using `-q/--no-quotes-preserved`)\n\nWith input :\n\n```yaml\n---\napiVersion: extensions/v1beta1 # with comment\nkind: ReplicaSet\nmetadata:\n  name: tname\n  namespace: tns\n  annotations:\n    string_no_quotes: frontend\n    string_single_quotes: 'frontend'\n    string_double_quotes: \"frontend\"\n    boolean_no_quotes: true\n    boolean_single_quotes: 'true'\n    boolean_double_quotes: \"true\"\n    number_no_quotes: 1\n    number_single_quotes: '1'\n    number_double_quotes: \"1\"\n```\n\nthe ouput will be :\n\n```yaml\n---\napiVersion: extensions/v1beta1 # with comment\nkind: ReplicaSet\nmetadata:\n  name: tname\n  namespace: tns\n  annotations:\n    string_no_quotes: frontend\n    string_single_quotes: frontend\n    string_double_quotes: frontend\n    boolean_no_quotes: true\n    boolean_single_quotes: 'true'\n    boolean_double_quotes: 'true'\n    number_no_quotes: 1\n    number_single_quotes: '1'\n    number_double_quotes: '1'\n\n```\n\n**Note** : `kubesplit` is not fully _Kubernetes_ aware for the moment, so it does not try to enforce this behaviour only on string sensible _kubernetes_ resource fields (`.metadata.annotations` and `.spec.containers.environment` values)\n\n## TODO\n\n- Provide an option to enforce the quote type (by default, with `--no-quotes-preserved` boolean and integers are forced with single quotes) Hint =\u003e \u003chttps://stackoverflow.com/questions/56588374/when-using-ruamel-yaml-and-preserve-quotes-true-is-there-a-way-to-force-roundtri/56592388#56592388\u003e\n\n## Contribute\n\n```bash\n# Setup a local virtual env (needed once)\npython3 -m venv .venv\n# Activate\nsource .venv/bin/activate.fish # \u003c= adjust\n# Install requirements\npip install -r requirements_dev.txt\n# Run locally\npython -m kubesplit -h\n# All make targets\nmake\n# Tests anyone?\nmake test\n# hack hack\n# push PR\n```\n\n## Credits\n\n- This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) and the [audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage) project template.\n- Kubesplit uses the awesome [ruamel.yaml](https://yaml.readthedocs.io/en/latest/pyyaml.html) python lib.\n- Dependencies scanned by [PyUp.io](https://pyup.io/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flooztra%2Fkubesplit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flooztra%2Fkubesplit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flooztra%2Fkubesplit/lists"}