├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .konfig.yaml ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── doc └── USAGE.md ├── konfig └── test ├── common.bash ├── konfig.bats └── testdata ├── config-2 ├── config1 ├── config12 ├── config12-flat ├── config123 ├── config123-flat ├── config13-flat ├── config2-flat ├── config23 ├── config23-flat ├── config3 └── credentials ├── dummy-ca.crt ├── dummy-client.crt └── dummy-client.key /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: konfig CI 2 | on: 3 | push: 4 | branches: 5 | - '*' 6 | tags: 7 | - 'v*.*.*' 8 | pull_request: 9 | branches: 10 | - '*' 11 | 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | 18 | - name: Check out repo 19 | uses: actions/checkout@v2 20 | 21 | - name: Shellcheck 22 | uses: ludeeus/action-shellcheck@master 23 | env: 24 | SHELLCHECK_OPTS: -e SC2155 25 | 26 | - name: Run tests 27 | run: | 28 | set -euo pipefail 29 | sudo apt-get update -qq 30 | sudo apt-get install -qq bats 31 | # To make 'no kubectl detected' test work, place kubectl in /usr/local/bin/ 32 | sudo curl -fsSL -o /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.21.3/bin/linux/amd64/kubectl 33 | sudo chmod +x /usr/local/bin/kubectl 34 | make test 35 | 36 | - name: Create assets 37 | if: contains(github.ref, 'tags') 38 | run: make deploy 39 | 40 | - name: Create release 41 | if: contains(github.ref, 'tags') 42 | uses: actions/create-release@v1 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | with: 46 | tag_name: ${{ github.ref }} 47 | release_name: Release ${{ github.ref }} 48 | draft: false 49 | prerelease: false 50 | 51 | - name: Upload assets 52 | if: contains(github.ref, 'tags') 53 | uses: svenstaro/upload-release-action@v1-release 54 | with: 55 | repo_token: ${{ secrets.GITHUB_TOKEN }} 56 | file: out/bundle.tar.gz* 57 | tag: ${{ github.ref }} 58 | overwrite: true 59 | file_glob: true 60 | 61 | - name: Create PR in krew-index 62 | if: contains(github.ref, 'tags') 63 | uses: rajatjindal/krew-release-bot@v0.0.40 64 | with: 65 | krew_template_file: .konfig.yaml 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /hack/ 2 | /out/ 3 | /.idea/ 4 | -------------------------------------------------------------------------------- /.konfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: krew.googlecontainertools.github.com/v1alpha2 2 | kind: Plugin 3 | metadata: 4 | name: konfig 5 | spec: 6 | version: "{{ .TagName }}" 7 | platforms: 8 | - {{addURIAndSha "https://github.com/corneliusweig/konfig/releases/download/{{ .TagName }}/bundle.tar.gz" .TagName | indent 6 }} 9 | bin: konfig-krew 10 | files: 11 | - from: ./konfig-krew 12 | to: . 13 | - from: LICENSE 14 | to: . 15 | selector: 16 | matchExpressions: 17 | - key: os 18 | operator: In 19 | values: ["darwin", "linux"] 20 | shortDescription: Merge, split or import kubeconfig files 21 | homepage: https://github.com/corneliusweig/konfig 22 | description: |+2 23 | 24 | konfig helps to merge, split or import kubeconfig files 25 | 26 | This is a convenience wrapper around the `kubectl config view` command. 27 | 28 | Usage: 29 | $ kubectl konfig import --save new-cfg 30 | $ kubectl konfig merge kubeconfig1 kubeconfig2 > merged 31 | $ kubectl konfig export ctx1 ctx2 -k k8s.yaml,k3s.yaml > extracted 32 | 33 | More on https://github.com/corneliusweig/konfig/blob/master/doc/USAGE.md#konfig 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | `konfig` uses GitHub to manage reviews of pull requests. 3 | 4 | * If you have a trivial fix or improvement, go ahead and create a pull request. 5 | 6 | * Code must be properly formatted 7 | 8 | ## Building & Testing 9 | 10 | This repository uses [bats](https://github.com/sstephenson/bats) for testing. 11 | To run the tests, install `bats`, then 12 | ```bash 13 | make test 14 | ``` 15 | 16 | ## Pull Request Checklist 17 | 18 | * Add a [DCO](https://developercertificate.org/) / `Signed-off-by` line in any commit message (`git commit --signoff`). 19 | 20 | * Branch from master and, if needed, rebase to the current master branch before submitting your pull request. 21 | If it doesn't merge cleanly with master you will be asked to rebase your changes. 22 | 23 | * Commits should be small units of work with one topic. Each commit should be correct independently. 24 | 25 | * Add tests relevant to the fixed bug or new feature. 26 | 27 | ## Releases 28 | 29 | This is a checklist for new releases: 30 | 31 | 0. Create release notes in `doc/releases` 32 | 0. Update usage instructions, if applicable 33 | 0. Create a new tag via `hack/make_tag.sh` 34 | 0. Push the tag to GitHub `git push --tags` 35 | 0. Create new release on GitHub Releases and upload artifacts 36 | 0. Update [krew-index](https://github.com/GoogleContainerTools/krew-index) 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Cornelius Weig 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | OUTPUTDIR:=out 16 | ASSETS:=konfig-krew LICENSE 17 | 18 | %.sha256: % 19 | sha256sum $< > $@ 20 | 21 | .PRECIOUS: %.gz 22 | %.gz: % 23 | gzip --best -f $< 24 | 25 | $(OUTPUTDIR)/bundle.tar: $(ASSETS) $(OUTPUTDIR) 26 | tar cf $@ $(ASSETS) 27 | 28 | %-krew: % 29 | sed "/cat <<'EOF'/,/^EOF/s:konfig:kubectl konfig:" $< > $@ 30 | chmod +x $@ 31 | 32 | $(OUTPUTDIR): 33 | mkdir -p $@ 34 | 35 | .PHONY: test 36 | test: 37 | cd test && bats konfig.bats 38 | 39 | .PHONY: deploy 40 | deploy: out/bundle.tar.gz.sha256 41 | 42 | .PHONY: clean 43 | clean: 44 | $(RM) -r -- $(OUTPUTDIR) konfig-krew 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # konfig 2 | 3 | ![Latest GitHub release](https://img.shields.io/github/release/corneliusweig/konfig.svg) 4 | ![GitHub workflow status](https://img.shields.io/github/workflow/status/corneliusweig/konfig/konfig%20CI) 5 | ![Written in Bash](https://img.shields.io/badge/written%20in-bash-19bb19.svg) 6 | 7 | 8 | konfig helps to merge, split or import kubeconfig files 9 | 10 | ## Usage 11 | 12 | ### Import a kubeconfig 13 | ```bash 14 | konfig import --save new-cfg 15 | ``` 16 | Imports the config file `new-cfg` into the default kubeconfig at `~/.kube/config`. 17 | To show the result without changing your kubeconfig, do 18 | ```bash 19 | konfig import new-cfg 20 | ``` 21 | 22 | CAVEAT: due to how shells work, the following will lose your current `~/.kube/config` 23 | ```bash 24 | # WRONG, don't do this! 25 | konfig import new-cfg > ~/.kube/config 26 | ``` 27 | 28 | ### Merge several kubeconfig files 29 | ```bash 30 | konfig merge config1 config2 > merged-config 31 | ``` 32 | This variant creates a self-contained kubeconfig where all credentials are stored inline in the kubeconfig. 33 | If you want to preserve the structure and keep credentials separate, use `--preserve-structure`. 34 | 35 | ### Extract a minimal kubeconfig for one or several contexts 36 | This will extract a minimal kubeconfig with a single context `minikube`: 37 | ```bash 38 | # extract context minikube from the default kubeconfig 39 | konfig export minikube > minikube.config 40 | 41 | # extract context minikube and docker-for-desktop from two input configs 42 | konfig export minikube docker-for-desktop -k ~/.kube/other,~/dockercfg > local 43 | ``` 44 | 45 | ## Installation 46 | There are several ways to install `konfig`. 47 | The recommended installation method is via `krew`. 48 | 49 | ### Via krew 50 | Krew is the `kubectl` plugin manager. If you have not yet installed `krew`, get it at 51 | [https://github.com/kubernetes-sigs/krew](https://github.com/kubernetes-sigs/krew). 52 | Then installation is as simple as 53 | ```bash 54 | kubectl krew install konfig 55 | ``` 56 | The plugin will be available as `kubectl konfig`, see [doc/USAGE](doc/USAGE.md) for further details. You could also define an alias as well: `alias konfig = 'kubectl konfig'` 57 | 58 | ### Manual 59 | When using the binaries for installation, also have a look at [USAGE](#Usage). 60 | 61 | #### OSX & Linux 62 | ```bash 63 | curl -Lo konfig https://github.com/corneliusweig/konfig/raw/v0.2.6/konfig \ 64 | && chmod +x konfig \ 65 | && sudo mv -i konfig /usr/local/bin 66 | ``` 67 | Feel free to change the `sudo mv` to put `konfig` in some other location from your `$PATH` variable. 68 | 69 | #### Windows 70 | > If you figure out how to run `konfig` on Windows, please send a PR with instructions. 71 | -------------------------------------------------------------------------------- /doc/USAGE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # konfig 4 | konfig helps to merge, split or import kubeconfig files 5 | 6 | ## Usage 7 | 8 | The following assumes that you have installed `konfig` via 9 | ```bash 10 | kubectl krew install konfig 11 | ``` 12 | 13 | ### Import a kubeconfig 14 | ```bash 15 | kubectl konfig import --save new-cfg 16 | ``` 17 | Imports the config file `new-cfg` into the default kubeconfig at `~/.kube/config`. 18 | To show the result without changing your kubeconfig, do 19 | ```bash 20 | kubectl konfig import new-cfg 21 | ``` 22 | 23 | CAVEAT: due to how shells work, the following will lose your current `~/.kube/config` 24 | ```bash 25 | # WRONG, don't do this! 26 | kubectl konfig import new-cfg > ~/.kube/config 27 | ``` 28 | 29 | ### Merge several kubeconfig files 30 | ```bash 31 | kubectl konfig merge config1 config2 > merged-config 32 | ``` 33 | This variant creates a self-contained kubeconfig where all credentials are stored inline in the kubeconfig. 34 | If you want to preserve the structure and keep credentials separate, use `--preserve-structure`. 35 | 36 | ### Extract a minimal kubeconfig for one or several contexts 37 | This will extract a minimal kubeconfig with a single context `minikube`: 38 | ```bash 39 | # extract context minikube from the default kubeconfig 40 | kubectl konfig export minikube > minikube.config 41 | 42 | # extract context minikube and docker-for-desktop from two input configs 43 | kubectl konfig export minikube docker-for-desktop -k ~/.kube/other,~/dockercfg > local 44 | ``` 45 | -------------------------------------------------------------------------------- /konfig: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 Cornelius Weig 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | [[ -n $DEBUG ]] && set -x 18 | 19 | set -eEuo pipefail 20 | 21 | declare -a TMPFILES=() 22 | cleanup() { 23 | if [[ "${#TMPFILES[@]}" -gt 0 ]]; then 24 | rm -- "${TMPFILES[@]}" 25 | fi 26 | } 27 | trap cleanup EXIT 28 | 29 | usage() { 30 | cat <<'EOF' 31 | konfig helps to merge, split or import kubeconfig files 32 | 33 | USAGE: 34 | konfig merge [--preserve-structure,-p] .. 35 | Merge multiple kubeconfigs into one. 36 | -p prevents flattening which will make the result less portable. 37 | 38 | konfig import [--preserve-structure,-p] [--save,-s] [--stdin,-i] .. 39 | Import the given configs into your current kubeconfig (respects KUBECONFIG env var). 40 | -s writes the result to your ~/.kube/config 41 | -i import kubeconfig string from stdin 42 | 43 | konfig split .. [--kubeconfig,-k ] 44 | konfig export .. [--kubeconfig,-k ] 45 | Export/split off a minimal kubeconfig with the given contexts 46 | -k may be repeated or contain a comma-delimited list of input configs. 47 | When omitted, export from the default kubeconfig. 48 | 49 | EXAMPLES: 50 | Merge new-cfg with your current kubeconfig 51 | $ konfig import new-cfg 52 | and save the result to ~/.kube/config 53 | $ konfig import --save new-cfg 54 | CAVEAT: due to how shells work, the following will lose your current ~/.kube/config 55 | WRONG $ konfig import new-cfg > ~/.kube/config 56 | 57 | Export ctx1 and ctx2 into combined.yaml 58 | $ konfig export -k ~/.kube/config -k k3s.yaml ctx1 ctx2 > combined.yaml 59 | 60 | Merge two configs 61 | $ konfig merge ~/.kube/config k3s.yaml > merged-and-flattened 62 | or 63 | $ konfig merge -p ~/.kube/config k3s.yaml > merged-not-flattened 64 | 65 | EOF 66 | } 67 | 68 | error() { 69 | echo "error: $1" >&2 70 | exit 1 71 | } 72 | 73 | merge() { 74 | if [[ "$1" =~ ^-.+ && "$1" != '-p' && "$1" != '--preserve-structure' ]]; then 75 | error "unrecognized flag \"$1\"" 76 | else 77 | IFS=$':\n\t' 78 | if [[ "$1" == '-p' || "$1" == '--preserve-structure' ]]; then 79 | KUBECONFIG="${*:2}" $KUBECTL config view --raw --merge 80 | else 81 | KUBECONFIG="$*" $KUBECTL config view --flatten --merge 82 | fi 83 | IFS=$' \t\n' 84 | fi 85 | } 86 | 87 | import_ctx() { 88 | declare -a tmpcfgs=() 89 | local tmpcfg 90 | local tmpinputcfg="" 91 | local out="" 92 | local arg="" 93 | 94 | tmpcfg=$(mktemp konfig_XXXXXX) 95 | TMPFILES+=( "$tmpcfg" ) 96 | tmpcfgs+=( "$tmpcfg") 97 | 98 | for OPT in "$@"; do 99 | case $OPT in 100 | -p | --preserve-structure) 101 | arg="$1" 102 | shift 103 | ;; 104 | -s | --save) 105 | out="${XDG_CACHE_HOME:-$HOME/.kube}/config" 106 | shift 107 | ;; 108 | -i | --stdin) 109 | if [[ -p /dev/stdin ]]; then 110 | tmpinputcfg=$(mktemp konfig_input_XXXXXX) 111 | TMPFILES+=( "$tmpinputcfg" ) 112 | tmpcfgs+=( "$tmpinputcfg" ) 113 | cat - > "$tmpinputcfg" 114 | shift 115 | fi 116 | ;; 117 | -*) 118 | error "unrecognized flag \"$1\"" 119 | ;; 120 | esac 121 | done 122 | $KUBECTL config view --raw > "$tmpcfg" 123 | 124 | if [[ -z "$out" ]]; then 125 | merge "$arg" "${tmpcfgs[@]}" "$@" 126 | else 127 | trap 'mv "$tmpcfg" "$out"' ERR 128 | merge "$arg" "${tmpcfgs[@]}" "$@" > "$out" 129 | fi 130 | } 131 | 132 | export_contexts() { 133 | declare -a ctxs=() 134 | declare -a cfgs=() 135 | declare -a tmpcfgs=() 136 | local tmpcfg 137 | 138 | while [[ "$#" -gt 0 ]]; do 139 | if [[ "$1" == '--kubeconfig' || "$1" == '-k' ]]; then 140 | cfgs+=( "${2//,/:}" ) 141 | shift 2 142 | elif [[ "$1" =~ ^-.+ ]]; then 143 | error "unrecognized flag \"$1\"" 144 | else 145 | ctxs+=( "$1" ) 146 | shift 147 | fi 148 | done 149 | 150 | if [[ "${#ctxs[@]}" -eq 0 ]]; then 151 | error "contexts to export are missing" 152 | fi 153 | 154 | for x in "${ctxs[@]}"; do 155 | tmpcfg=$(mktemp konfig_XXXXXX) 156 | TMPFILES+=( "$tmpcfg" ) 157 | tmpcfgs+=( "$tmpcfg" ) 158 | if [[ "${#cfgs[@]}" -eq 0 ]]; then 159 | $KUBECTL config view --flatten --minify --context="$x" > "$tmpcfg" 160 | else 161 | IFS=$':\n\t' 162 | KUBECONFIG="${cfgs[*]}" $KUBECTL config view --flatten --minify --context="$x" > "$tmpcfg" 163 | IFS=$' \n\t' 164 | fi 165 | done 166 | 167 | merge "${tmpcfgs[@]}" 168 | } 169 | 170 | main() { 171 | if hash kubectl 2>/dev/null; then 172 | KUBECTL=kubectl 173 | elif hash kubectl.exe 2>/dev/null; then 174 | KUBECTL=kubectl.exe 175 | else 176 | echo >&2 "kubectl is not installed" 177 | exit 1 178 | fi 179 | 180 | if [[ "$#" -eq 0 ]]; then 181 | usage 182 | return 183 | fi 184 | 185 | case "$1" in 186 | '-h' | '--help' | 'help') 187 | usage 188 | ;; 189 | 'export'|'split') 190 | export_contexts "${@:2}" 191 | ;; 192 | 'import') 193 | import_ctx "${@:2}" 194 | ;; 195 | 'merge') 196 | merge "${@:2}" 197 | ;; 198 | -*) 199 | usage 200 | error "unrecognized flag \"${1}\"" 201 | ;; 202 | *) 203 | usage 204 | error "unknown command \"$1\"" 205 | esac 206 | 207 | } 208 | 209 | main "$@" 210 | -------------------------------------------------------------------------------- /test/common.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2019 Cornelius Weig 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # bats setup function 18 | setup() { 19 | export XDG_CACHE_HOME="$(mktemp -d)" 20 | export KUBECONFIG="${XDG_CACHE_HOME}/config" 21 | } 22 | 23 | # bats teardown function 24 | teardown() { 25 | rm -rf "$XDG_CACHE_HOME" 26 | } 27 | 28 | use_config() { 29 | cp "$BATS_TEST_DIRNAME/testdata/$1" "$KUBECONFIG" 30 | } 31 | 32 | check_kubeconfig() { 33 | diff -U3 "${1}" "${XDG_CACHE_HOME}/config" && echo 'same' || echo 'different' 34 | } 35 | 36 | check_fixture() { 37 | diff -U3 "${1}" <(echo "${2}") && echo 'same' || echo 'different' 38 | } 39 | -------------------------------------------------------------------------------- /test/konfig.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | # Copyright 2019 Cornelius Weig 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | COMMAND="$BATS_TEST_DIRNAME/../konfig" 18 | 19 | load common 20 | 21 | #### HELP 22 | 23 | @test "help should not fail" { 24 | run ${COMMAND} help 25 | echo "$output" 26 | [[ "$status" -eq 0 ]] 27 | [[ "$output" = "konfig helps to merge"* ]] 28 | } 29 | 30 | @test "--help should not fail" { 31 | run ${COMMAND} --help 32 | echo "$output" 33 | [[ "$status" -eq 0 ]] 34 | [[ "$output" = "konfig helps to merge"* ]] 35 | } 36 | 37 | @test "-h should not fail" { 38 | run ${COMMAND} -h 39 | echo "$output" 40 | [[ "$status" -eq 0 ]] 41 | [[ "$output" = "konfig helps to merge"* ]] 42 | } 43 | 44 | @test "no arguments given" { 45 | run ${COMMAND} 46 | echo "$output" 47 | [[ "$status" -eq 0 ]] 48 | [[ "$output" = "konfig helps to merge"* ]] 49 | } 50 | 51 | #### MERGE 52 | 53 | @test "merge --preserve-structure: three configs" { 54 | run ${COMMAND} merge --preserve-structure testdata/config{1,-2,3} 55 | echo "$output" 56 | [[ "$status" -eq 0 ]] 57 | [[ $(check_fixture 'testdata/config123' "$output") = 'same' ]] 58 | } 59 | 60 | @test "vanilla merge: three configs" { 61 | run ${COMMAND} merge testdata/config{1,-2,3} 62 | echo "$output" 63 | [[ "$status" -eq 0 ]] 64 | [[ $(check_fixture 'testdata/config123-flat' "$output") = 'same' ]] 65 | } 66 | 67 | @test "vanilla merge: single config" { 68 | run ${COMMAND} merge testdata/config123 69 | echo "$output" 70 | [[ "$status" -eq 0 ]] 71 | [[ $(check_fixture 'testdata/config123-flat' "$output") = 'same' ]] 72 | } 73 | 74 | #### IMPORT 75 | 76 | @test "import single config and print to stdout" { 77 | use_config config1 78 | run ${COMMAND} import testdata/config-2 79 | echo "$output" 80 | [[ "$status" -eq 0 ]] 81 | [[ $(check_fixture 'testdata/config12-flat' "$output") = 'same' ]] 82 | } 83 | 84 | @test "import config with -- in name" { 85 | use_config config1 86 | cp testdata/config-2 testdata/config--2 87 | run ${COMMAND} import testdata/config--2 88 | rm testdata/config--2 89 | echo "$output" 90 | [[ "$status" -eq 0 ]] 91 | [[ $(check_fixture 'testdata/config12-flat' "$output") = 'same' ]] 92 | } 93 | 94 | @test "import multiple configs and print to stdout" { 95 | use_config config1 96 | run ${COMMAND} import testdata/config-2 testdata/config3 97 | echo "$output" 98 | [[ "$status" -eq 0 ]] 99 | [[ $(check_fixture 'testdata/config123-flat' "$output") = 'same' ]] 100 | } 101 | 102 | @test "import single config" { 103 | use_config config1 104 | run ${COMMAND} import --save testdata/config-2 105 | echo "$output" 106 | [[ "$status" -eq 0 ]] 107 | [[ $(check_kubeconfig 'testdata/config12-flat') = 'same' ]] 108 | } 109 | 110 | @test "import multiple configs" { 111 | use_config config1 112 | run ${COMMAND} import -s testdata/config-2 testdata/config3 113 | echo "$output" 114 | [[ "$status" -eq 0 ]] 115 | [[ $(check_kubeconfig 'testdata/config123-flat') = 'same' ]] 116 | } 117 | 118 | @test "import single config and preserve structure" { 119 | use_config config1 120 | run ${COMMAND} import --preserve-structure --save testdata/config-2 121 | echo "$output" 122 | [[ "$status" -eq 0 ]] 123 | [[ $(check_kubeconfig 'testdata/config12') = 'same' ]] 124 | } 125 | 126 | @test "import multiple configs and preserve structure" { 127 | use_config config1 128 | run ${COMMAND} import -p -s testdata/config-2 testdata/config3 129 | echo "$output" 130 | [[ "$status" -eq 0 ]] 131 | [[ $(check_kubeconfig 'testdata/config123') = 'same' ]] 132 | } 133 | 134 | @test "import single config from stdin and print to stdout" { 135 | use_config config1 136 | run bash -c "cat testdata/config3 | ${COMMAND} import -i" 137 | echo "$output" 138 | [[ "$status" -eq 0 ]] 139 | [[ $(check_fixture 'testdata/config13-flat' "$output") = 'same' ]] 140 | } 141 | 142 | @test "import single config from stdin" { 143 | use_config config1 144 | run bash -c "cat testdata/config3 | ${COMMAND} import -i --save" 145 | echo "$output" 146 | [[ "$status" -eq 0 ]] 147 | [[ $(check_kubeconfig 'testdata/config13-flat') = 'same' ]] 148 | } 149 | 150 | @test "import no stdin should preserve .kube/config" { 151 | use_config config1 152 | run ${COMMAND} import -i --save 153 | [[ "$status" -eq 0 ]] 154 | [[ $(check_kubeconfig 'testdata/config1') = 'same' ]] 155 | } 156 | 157 | @test "import invalid file from stdin should preserve .kube/config" { 158 | use_config config1 159 | run bash -c "echo invalid | ${COMMAND} import -i --save" 160 | echo "$output" 161 | [[ "$status" -eq 1 ]] 162 | [[ $(check_kubeconfig 'testdata/config1') = 'same' ]] 163 | } 164 | 165 | @test "failed read of imported config should preserve .kube/config" { 166 | use_config config1 167 | chmod u-r testdata/config-2 168 | run ${COMMAND} import -s /does/not/exist testdata/config-2 169 | chmod u+r testdata/config-2 170 | echo "$output" 171 | [[ "$status" -eq 1 ]] 172 | [[ $(check_kubeconfig 'testdata/config1') = 'same' ]] 173 | } 174 | 175 | #### EXPORT 176 | 177 | @test "exporting with '--kubeconfig' yields original config - I" { 178 | run ${COMMAND} export context1 --kubeconfig testdata/config123 179 | echo "$output" 180 | [[ "$status" -eq 0 ]] 181 | [[ $(check_fixture 'testdata/config1' "$output") = 'same' ]] 182 | } 183 | 184 | @test "exporting with '--kubeconfig' yields original config - II" { 185 | run ${COMMAND} export -k testdata/config123 context2 186 | echo "$output" 187 | [[ "$status" -eq 0 ]] 188 | [[ $(check_fixture 'testdata/config2-flat' "$output") = 'same' ]] 189 | } 190 | 191 | @test "exporting with KUBECONFIG yields original config" { 192 | use_config config123 193 | run ${COMMAND} export context3 194 | echo "$output" 195 | [[ "$status" -eq 0 ]] 196 | [[ $(check_fixture 'testdata/config3' "$output") = 'same' ]] 197 | } 198 | 199 | @test "exporting with multiple from multiple kubeconfigs - I" { 200 | run ${COMMAND} split context2 context3 -k testdata/config1,testdata/config3 --kubeconfig testdata/config-2 201 | echo "$output" 202 | [[ "$status" -eq 0 ]] 203 | [[ $(check_fixture 'testdata/config23-flat' "$output") = 'same' ]] 204 | } 205 | 206 | @test "exporting with multiple from multiple kubeconfigs - II" { 207 | run ${COMMAND} split -k testdata/config1 context1 --kubeconfig testdata/config23 context2 208 | echo "$output" 209 | [[ "$status" -eq 0 ]] 210 | [[ $(check_fixture 'testdata/config12-flat' "$output") = 'same' ]] 211 | } 212 | 213 | @test "exporting without any context - I" { 214 | run ${COMMAND} export -k testdata/config1 -k testdata/config23 215 | echo "$output" 216 | [[ "$status" -eq 1 ]] 217 | [[ "$output" = *"error: contexts to export are missing"* ]] 218 | } 219 | 220 | @test "exporting without any context - II" { 221 | run ${COMMAND} export 222 | echo "$output" 223 | [[ "$status" -eq 1 ]] 224 | [[ "$output" = *"error: contexts to export are missing"* ]] 225 | } 226 | 227 | #### ERRORS 228 | 229 | @test "no kubectl detected" { 230 | OLDPATH="$PATH" 231 | PATH=/bin 232 | run ${COMMAND} 233 | echo "$output" 234 | [[ "$status" -eq 1 ]] 235 | [[ "$output" = "kubectl is not installed" ]] 236 | PATH="$OLDPATH" 237 | } 238 | 239 | @test "unknown subcommand" { 240 | run ${COMMAND} foobar 241 | echo "$output" 242 | [[ "$status" -eq 1 ]] 243 | [[ "$output" = *"error: unknown command \"foobar\""* ]] 244 | } 245 | 246 | @test "unknown flag - export" { 247 | run ${COMMAND} export -u 248 | echo "$output" 249 | [[ "$status" -eq 1 ]] 250 | [[ "$output" = *"error: unrecognized flag \"-u\""* ]] 251 | } 252 | 253 | @test "unknown flag - import" { 254 | run ${COMMAND} import -u 255 | echo "$output" 256 | [[ "$status" -eq 1 ]] 257 | [[ "$output" = *"error: unrecognized flag \"-u\""* ]] 258 | } 259 | 260 | @test "unknown flag - merge" { 261 | run ${COMMAND} merge -u 262 | echo "$output" 263 | [[ "$status" -eq 1 ]] 264 | [[ "$output" = *"error: unrecognized flag \"-u\""* ]] 265 | } 266 | 267 | @test "unknown flag - I" { 268 | run ${COMMAND} -u 269 | echo "$output" 270 | [[ "$status" -eq 1 ]] 271 | [[ "$output" = *"error: unrecognized flag \"-u\""* ]] 272 | } 273 | 274 | @test "unknown flag - II" { 275 | run ${COMMAND} --unknown 276 | echo "$output" 277 | [[ "$status" -eq 1 ]] 278 | [[ "$output" = *"error: unrecognized flag \"--unknown\""* ]] 279 | } 280 | -------------------------------------------------------------------------------- /test/testdata/config-2: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority: credentials/dummy-ca.crt 5 | server: cluster.non-flat 6 | name: config-non-flat 7 | contexts: 8 | - context: 9 | cluster: config-non-flat 10 | user: config-non-flat 11 | name: context2 12 | current-context: context2 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: config-non-flat 17 | user: 18 | client-certificate: credentials/dummy-client.crt 19 | client-key: credentials/dummy-client.key 20 | -------------------------------------------------------------------------------- /test/testdata/config1: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.flat 6 | name: config-flat 7 | contexts: 8 | - context: 9 | cluster: config-flat 10 | user: config-flat 11 | name: context1 12 | current-context: context1 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: config-flat 17 | user: 18 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 19 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 20 | -------------------------------------------------------------------------------- /test/testdata/config12: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.flat 6 | name: config-flat 7 | - cluster: 8 | certificate-authority: credentials/dummy-ca.crt 9 | server: cluster.non-flat 10 | name: config-non-flat 11 | contexts: 12 | - context: 13 | cluster: config-flat 14 | user: config-flat 15 | name: context1 16 | - context: 17 | cluster: config-non-flat 18 | user: config-non-flat 19 | name: context2 20 | current-context: context1 21 | kind: Config 22 | preferences: {} 23 | users: 24 | - name: config-flat 25 | user: 26 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 27 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 28 | - name: config-non-flat 29 | user: 30 | client-certificate: credentials/dummy-client.crt 31 | client-key: credentials/dummy-client.key 32 | -------------------------------------------------------------------------------- /test/testdata/config12-flat: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.flat 6 | name: config-flat 7 | - cluster: 8 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 9 | server: cluster.non-flat 10 | name: config-non-flat 11 | contexts: 12 | - context: 13 | cluster: config-flat 14 | user: config-flat 15 | name: context1 16 | - context: 17 | cluster: config-non-flat 18 | user: config-non-flat 19 | name: context2 20 | current-context: context1 21 | kind: Config 22 | preferences: {} 23 | users: 24 | - name: config-flat 25 | user: 26 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 27 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 28 | - name: config-non-flat 29 | user: 30 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 31 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 32 | -------------------------------------------------------------------------------- /test/testdata/config123: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.flat 6 | name: config-flat 7 | - cluster: 8 | certificate-authority: credentials/dummy-ca.crt 9 | server: cluster.non-flat 10 | name: config-non-flat 11 | - cluster: 12 | certificate-authority-data: Y2VydGlmaWNhdGUtYXV0aG9yaXR5LWRhdGE= 13 | server: cluster.passwd 14 | name: config-passwd 15 | contexts: 16 | - context: 17 | cluster: config-flat 18 | user: config-flat 19 | name: context1 20 | - context: 21 | cluster: config-non-flat 22 | user: config-non-flat 23 | name: context2 24 | - context: 25 | cluster: config-passwd 26 | user: config-passwd 27 | name: context3 28 | current-context: context1 29 | kind: Config 30 | preferences: {} 31 | users: 32 | - name: config-flat 33 | user: 34 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 35 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 36 | - name: config-non-flat 37 | user: 38 | client-certificate: credentials/dummy-client.crt 39 | client-key: credentials/dummy-client.key 40 | - name: config-passwd 41 | user: 42 | password: not-a-secure-password 43 | username: admin 44 | -------------------------------------------------------------------------------- /test/testdata/config123-flat: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.flat 6 | name: config-flat 7 | - cluster: 8 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 9 | server: cluster.non-flat 10 | name: config-non-flat 11 | - cluster: 12 | certificate-authority-data: Y2VydGlmaWNhdGUtYXV0aG9yaXR5LWRhdGE= 13 | server: cluster.passwd 14 | name: config-passwd 15 | contexts: 16 | - context: 17 | cluster: config-flat 18 | user: config-flat 19 | name: context1 20 | - context: 21 | cluster: config-non-flat 22 | user: config-non-flat 23 | name: context2 24 | - context: 25 | cluster: config-passwd 26 | user: config-passwd 27 | name: context3 28 | current-context: context1 29 | kind: Config 30 | preferences: {} 31 | users: 32 | - name: config-flat 33 | user: 34 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 35 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 36 | - name: config-non-flat 37 | user: 38 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 39 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 40 | - name: config-passwd 41 | user: 42 | password: not-a-secure-password 43 | username: admin 44 | -------------------------------------------------------------------------------- /test/testdata/config13-flat: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.flat 6 | name: config-flat 7 | - cluster: 8 | certificate-authority-data: Y2VydGlmaWNhdGUtYXV0aG9yaXR5LWRhdGE= 9 | server: cluster.passwd 10 | name: config-passwd 11 | contexts: 12 | - context: 13 | cluster: config-flat 14 | user: config-flat 15 | name: context1 16 | - context: 17 | cluster: config-passwd 18 | user: config-passwd 19 | name: context3 20 | current-context: context1 21 | kind: Config 22 | preferences: {} 23 | users: 24 | - name: config-flat 25 | user: 26 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 27 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 28 | - name: config-passwd 29 | user: 30 | password: not-a-secure-password 31 | username: admin 32 | -------------------------------------------------------------------------------- /test/testdata/config2-flat: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.non-flat 6 | name: config-non-flat 7 | contexts: 8 | - context: 9 | cluster: config-non-flat 10 | user: config-non-flat 11 | name: context2 12 | current-context: context2 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: config-non-flat 17 | user: 18 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 19 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 20 | -------------------------------------------------------------------------------- /test/testdata/config23: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority: credentials/dummy-ca.crt 5 | server: cluster.non-flat 6 | name: config-non-flat 7 | - cluster: 8 | certificate-authority-data: Y2VydGlmaWNhdGUtYXV0aG9yaXR5LWRhdGE= 9 | server: cluster.passwd 10 | name: config-passwd 11 | contexts: 12 | - context: 13 | cluster: config-non-flat 14 | user: config-non-flat 15 | name: context2 16 | - context: 17 | cluster: config-passwd 18 | user: config-passwd 19 | name: context3 20 | current-context: context2 21 | kind: Config 22 | preferences: {} 23 | users: 24 | - name: config-non-flat 25 | user: 26 | client-certificate: credentials/dummy-client.crt 27 | client-key: credentials/dummy-client.key 28 | - name: config-passwd 29 | user: 30 | password: not-a-secure-password 31 | username: admin 32 | -------------------------------------------------------------------------------- /test/testdata/config23-flat: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: X19kdW1teS1jYS5jcnRfX2RhdGFfXwo= 5 | server: cluster.non-flat 6 | name: config-non-flat 7 | - cluster: 8 | certificate-authority-data: Y2VydGlmaWNhdGUtYXV0aG9yaXR5LWRhdGE= 9 | server: cluster.passwd 10 | name: config-passwd 11 | contexts: 12 | - context: 13 | cluster: config-non-flat 14 | user: config-non-flat 15 | name: context2 16 | - context: 17 | cluster: config-passwd 18 | user: config-passwd 19 | name: context3 20 | current-context: context2 21 | kind: Config 22 | preferences: {} 23 | users: 24 | - name: config-non-flat 25 | user: 26 | client-certificate-data: X19kdW1teS1jbGllbnQuY3J0X19kYXRhX18K 27 | client-key-data: X19kdW1teS1jbGllbnQua2V5X19kYXRhX18K 28 | - name: config-passwd 29 | user: 30 | password: not-a-secure-password 31 | username: admin 32 | -------------------------------------------------------------------------------- /test/testdata/config3: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: Y2VydGlmaWNhdGUtYXV0aG9yaXR5LWRhdGE= 5 | server: cluster.passwd 6 | name: config-passwd 7 | contexts: 8 | - context: 9 | cluster: config-passwd 10 | user: config-passwd 11 | name: context3 12 | current-context: context3 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: config-passwd 17 | user: 18 | password: not-a-secure-password 19 | username: admin 20 | -------------------------------------------------------------------------------- /test/testdata/credentials/dummy-ca.crt: -------------------------------------------------------------------------------- 1 | __dummy-ca.crt__data__ 2 | -------------------------------------------------------------------------------- /test/testdata/credentials/dummy-client.crt: -------------------------------------------------------------------------------- 1 | __dummy-client.crt__data__ 2 | -------------------------------------------------------------------------------- /test/testdata/credentials/dummy-client.key: -------------------------------------------------------------------------------- 1 | __dummy-client.key__data__ 2 | --------------------------------------------------------------------------------