From f86cb1426c0e2650f4e5e7088ace41d1dc741b48 Mon Sep 17 00:00:00 2001 From: Fatih Sever Date: Tue, 16 Jan 2024 12:39:13 +0300 Subject: [PATCH] Initial commit --- .github/workflows/ci.yml | 53 + .gitignore | 42 + CHANGELOG.md | 2 + LICENSE | 21 + README.md | 89 + analysis_options.yaml | 4 + assets/logo.svg | 4 + assets/logo.webp | Bin 0 -> 4444 bytes docs/.gitignore | 11 + docs/components/logo.js | 18 + docs/next.config.js | 16 + docs/package.json | 19 + docs/pages/_app.mdx | 5 + docs/pages/getting-started.mdx | 1 + docs/postcss.config.js | 6 + .../public/favicon/android-chrome-192x192.png | Bin 0 -> 14296 bytes .../public/favicon/android-chrome-512x512.png | Bin 0 -> 39535 bytes docs/public/favicon/apple-touch-icon.png | Bin 0 -> 12885 bytes docs/public/favicon/favicon-16x16.png | Bin 0 -> 799 bytes docs/public/favicon/favicon-32x32.png | Bin 0 -> 1801 bytes docs/public/favicon/favicon.ico | Bin 0 -> 15406 bytes docs/public/favicon/site.webmanifest | 1 + docs/styles/globals.css | 3 + docs/tailwind.config.js | 7 + docs/theme.config.js | 20 + docs/yarn.lock | 5278 +++++++++++++++++ example/dart/convert.dart | 29 + example/dart/merge.dart | 32 + example/dart/validate.dart | 30 + example/example.dart | 17 + example/js/convert.js | 1 + example/js/merge.js | 1 + example/js/validate.js | 1 + lib/kubeconfig.dart | 9 + lib/src/enums/enums.dart | 2 + lib/src/enums/interactive_mode.dart | 26 + lib/src/enums/validation_code.dart | 117 + lib/src/exceptions/exceptions.dart | 1 + lib/src/exceptions/kubeconfig_exception.dart | 244 + lib/src/extensions/extensions.dart | 2 + lib/src/extensions/object_extensions.dart | 146 + lib/src/extensions/string_extensions.dart | 32 + lib/src/kubeconfig_util.dart | 747 +++ lib/src/models/auth_info.dart | 128 + lib/src/models/auth_info.g.dart | 267 + lib/src/models/auth_provider_config.dart | 44 + lib/src/models/auth_provider_config.g.dart | 95 + lib/src/models/cluster.dart | 91 + lib/src/models/cluster.g.dart | 162 + lib/src/models/context.dart | 52 + lib/src/models/context.g.dart | 103 + lib/src/models/exec.dart | 101 + lib/src/models/exec.g.dart | 169 + lib/src/models/exec_env.dart | 45 + lib/src/models/exec_env.g.dart | 90 + lib/src/models/kubeconfig.dart | 158 + lib/src/models/kubeconfig.g.dart | 166 + lib/src/models/models.dart | 12 + lib/src/models/named_auth_info.dart | 45 + lib/src/models/named_auth_info.g.dart | 93 + lib/src/models/named_cluster.dart | 42 + lib/src/models/named_cluster.g.dart | 92 + lib/src/models/named_context.dart | 45 + lib/src/models/named_context.g.dart | 92 + lib/src/models/preferences.dart | 38 + lib/src/models/preferences.g.dart | 77 + lib/src/models/validation_result.dart | 45 + lib/src/models/validation_result.g.dart | 140 + pubspec.yaml | 27 + test/files/README.md | 1 + test/files/cert/README.md | 29 + test/files/cert/ca.crt | 20 + test/files/cert/ca.key | 27 + test/files/cert/example.crt | 20 + test/files/cert/example.csr | 17 + test/files/cert/example.key | 28 + test/files/cert/example_crt_base64.txt | 1 + test/files/cert/example_key_base64.txt | 1 + test/files/empty.yaml | 0 test/files/invalid.json | 1 + test/files/invalid.yaml | 1 + .../invalid_cluster_certificate_both.yaml | 20 + .../invalid_cluster_certificate_file.yaml | 19 + test/files/invalid_cluster_proxyurl.yaml | 20 + .../invalid_cluster_proxyurl_scheme.yaml | 20 + test/files/invalid_cluster_server.yaml | 18 + test/files/invalid_clusters_cluster.yaml | 16 + test/files/invalid_clusters_duplicate.yaml | 23 + test/files/invalid_clusters_name.yaml | 18 + test/files/invalid_clusters_required.yaml | 14 + test/files/invalid_context_cluster.yaml | 18 + .../invalid_context_cluster_missing.yaml | 19 + .../invalid_context_namespace_format.yaml | 20 + .../invalid_context_namespace_length.yaml | 20 + test/files/invalid_context_user.yaml | 18 + test/files/invalid_context_user_missing.yaml | 19 + test/files/invalid_contexts_context.yaml | 16 + test/files/invalid_contexts_duplicate.yaml | 23 + test/files/invalid_contexts_name.yaml | 18 + test/files/invalid_contexts_required.yaml | 14 + test/files/invalid_current_context.yaml | 19 + test/files/invalid_user_auth_provider.yaml | 22 + test/files/invalid_user_certificate_both.yaml | 20 + test/files/invalid_user_certificate_file.yaml | 19 + test/files/invalid_user_clientkey_both.yaml | 20 + test/files/invalid_user_clientkey_file.yaml | 19 + .../files/invalid_user_clientkey_missing.yaml | 18 + .../invalid_user_exec_apiversion_missing.yaml | 27 + .../invalid_user_exec_command_missing.yaml | 27 + .../invalid_user_exec_envname_missing.yaml | 27 + ...lid_user_exec_interactivemode_missing.yaml | 27 + test/files/invalid_user_impersonating.yaml | 21 + test/files/invalid_user_multi_auth.yaml | 20 + test/files/invalid_users_duplicate.yaml | 23 + test/files/invalid_users_name.yaml | 18 + test/files/invalid_users_required.yaml | 14 + test/files/invalid_users_user.yaml | 16 + test/files/token.txt | 1 + test/files/valid.json | 33 + test/files/valid.yaml | 19 + test/files/valid_multi.json | 253 + test/files/valid_multi.yaml | 159 + test/kubeconfig_merge_test.dart | 70 + test/kubeconfig_test.dart | 466 ++ test/kubeconfig_validation_test.dart | 446 ++ 125 files changed, 11759 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 analysis_options.yaml create mode 100644 assets/logo.svg create mode 100644 assets/logo.webp create mode 100644 docs/.gitignore create mode 100644 docs/components/logo.js create mode 100644 docs/next.config.js create mode 100644 docs/package.json create mode 100644 docs/pages/_app.mdx create mode 100644 docs/pages/getting-started.mdx create mode 100644 docs/postcss.config.js create mode 100644 docs/public/favicon/android-chrome-192x192.png create mode 100644 docs/public/favicon/android-chrome-512x512.png create mode 100644 docs/public/favicon/apple-touch-icon.png create mode 100644 docs/public/favicon/favicon-16x16.png create mode 100644 docs/public/favicon/favicon-32x32.png create mode 100644 docs/public/favicon/favicon.ico create mode 100644 docs/public/favicon/site.webmanifest create mode 100644 docs/styles/globals.css create mode 100644 docs/tailwind.config.js create mode 100644 docs/theme.config.js create mode 100644 docs/yarn.lock create mode 100644 example/dart/convert.dart create mode 100644 example/dart/merge.dart create mode 100644 example/dart/validate.dart create mode 100644 example/example.dart create mode 100644 example/js/convert.js create mode 100644 example/js/merge.js create mode 100644 example/js/validate.js create mode 100644 lib/kubeconfig.dart create mode 100644 lib/src/enums/enums.dart create mode 100644 lib/src/enums/interactive_mode.dart create mode 100644 lib/src/enums/validation_code.dart create mode 100644 lib/src/exceptions/exceptions.dart create mode 100644 lib/src/exceptions/kubeconfig_exception.dart create mode 100644 lib/src/extensions/extensions.dart create mode 100644 lib/src/extensions/object_extensions.dart create mode 100644 lib/src/extensions/string_extensions.dart create mode 100644 lib/src/kubeconfig_util.dart create mode 100644 lib/src/models/auth_info.dart create mode 100644 lib/src/models/auth_info.g.dart create mode 100644 lib/src/models/auth_provider_config.dart create mode 100644 lib/src/models/auth_provider_config.g.dart create mode 100644 lib/src/models/cluster.dart create mode 100644 lib/src/models/cluster.g.dart create mode 100644 lib/src/models/context.dart create mode 100644 lib/src/models/context.g.dart create mode 100644 lib/src/models/exec.dart create mode 100644 lib/src/models/exec.g.dart create mode 100644 lib/src/models/exec_env.dart create mode 100644 lib/src/models/exec_env.g.dart create mode 100644 lib/src/models/kubeconfig.dart create mode 100644 lib/src/models/kubeconfig.g.dart create mode 100644 lib/src/models/models.dart create mode 100644 lib/src/models/named_auth_info.dart create mode 100644 lib/src/models/named_auth_info.g.dart create mode 100644 lib/src/models/named_cluster.dart create mode 100644 lib/src/models/named_cluster.g.dart create mode 100644 lib/src/models/named_context.dart create mode 100644 lib/src/models/named_context.g.dart create mode 100644 lib/src/models/preferences.dart create mode 100644 lib/src/models/preferences.g.dart create mode 100644 lib/src/models/validation_result.dart create mode 100644 lib/src/models/validation_result.g.dart create mode 100644 pubspec.yaml create mode 100644 test/files/README.md create mode 100644 test/files/cert/README.md create mode 100644 test/files/cert/ca.crt create mode 100644 test/files/cert/ca.key create mode 100644 test/files/cert/example.crt create mode 100644 test/files/cert/example.csr create mode 100644 test/files/cert/example.key create mode 100644 test/files/cert/example_crt_base64.txt create mode 100644 test/files/cert/example_key_base64.txt create mode 100644 test/files/empty.yaml create mode 100644 test/files/invalid.json create mode 100644 test/files/invalid.yaml create mode 100644 test/files/invalid_cluster_certificate_both.yaml create mode 100644 test/files/invalid_cluster_certificate_file.yaml create mode 100644 test/files/invalid_cluster_proxyurl.yaml create mode 100644 test/files/invalid_cluster_proxyurl_scheme.yaml create mode 100644 test/files/invalid_cluster_server.yaml create mode 100644 test/files/invalid_clusters_cluster.yaml create mode 100644 test/files/invalid_clusters_duplicate.yaml create mode 100644 test/files/invalid_clusters_name.yaml create mode 100644 test/files/invalid_clusters_required.yaml create mode 100644 test/files/invalid_context_cluster.yaml create mode 100644 test/files/invalid_context_cluster_missing.yaml create mode 100644 test/files/invalid_context_namespace_format.yaml create mode 100644 test/files/invalid_context_namespace_length.yaml create mode 100644 test/files/invalid_context_user.yaml create mode 100644 test/files/invalid_context_user_missing.yaml create mode 100644 test/files/invalid_contexts_context.yaml create mode 100644 test/files/invalid_contexts_duplicate.yaml create mode 100644 test/files/invalid_contexts_name.yaml create mode 100644 test/files/invalid_contexts_required.yaml create mode 100644 test/files/invalid_current_context.yaml create mode 100644 test/files/invalid_user_auth_provider.yaml create mode 100644 test/files/invalid_user_certificate_both.yaml create mode 100644 test/files/invalid_user_certificate_file.yaml create mode 100644 test/files/invalid_user_clientkey_both.yaml create mode 100644 test/files/invalid_user_clientkey_file.yaml create mode 100644 test/files/invalid_user_clientkey_missing.yaml create mode 100644 test/files/invalid_user_exec_apiversion_missing.yaml create mode 100644 test/files/invalid_user_exec_command_missing.yaml create mode 100644 test/files/invalid_user_exec_envname_missing.yaml create mode 100644 test/files/invalid_user_exec_interactivemode_missing.yaml create mode 100644 test/files/invalid_user_impersonating.yaml create mode 100644 test/files/invalid_user_multi_auth.yaml create mode 100644 test/files/invalid_users_duplicate.yaml create mode 100644 test/files/invalid_users_name.yaml create mode 100644 test/files/invalid_users_required.yaml create mode 100644 test/files/invalid_users_user.yaml create mode 100644 test/files/token.txt create mode 100644 test/files/valid.json create mode 100644 test/files/valid.yaml create mode 100644 test/files/valid_multi.json create mode 100644 test/files/valid_multi.yaml create mode 100644 test/kubeconfig_merge_test.dart create mode 100644 test/kubeconfig_test.dart create mode 100644 test/kubeconfig_validation_test.dart diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..115e754 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +# Build, format, analyze and test the Dart code. +name: CI + +on: + # Runs on pull requests and pushes targeting the default branch + pull_request: + push: + branches: [main] + paths-ignore: + - "docs/**" + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages. +permissions: + contents: read + +jobs: + ci: + name: Dart CI + runs-on: ubuntu-latest + if: github.event.pull_request.draft == false + steps: + - name: Git Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Setup Dart + uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d # v1.6.0 + - name: Install dependencies + run: dart pub get + - name: Verify formatting + run: dart format — output=none — set-exit-if-changed . + - name: Analyze project source + run: dart analyze + - name: Run tests + run: | + dart pub global activate coverage + dart pub global run coverage:test_with_coverage + - name: Upload Coverage + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 + with: + directory: ./coverage + token: ${{ secrets.CODECOV_TOKEN }} + - name: Verify Coverage + uses: VeryGoodOpenSource/very_good_coverage@3b475421464c564c0714d92ce02742bd81fa9eda # v2.2.0 + with: + min_coverage: "100" + - name: Verify Pub Score + run: | + dart pub global activate pana + sudo apt-get install webp + PANA=$(pana . --no-warning); PANA_SCORE=$(echo $PANA | sed -n "s/.*Points: \([0-9]*\)\/\([0-9]*\)./\1\/\2/p") + echo "score: $PANA_SCORE" + IFS='/'; read -a SCORE_ARR <<< "$PANA_SCORE"; SCORE=SCORE_ARR[0]; TOTAL=SCORE_ARR[1] + if [ -z "$1" ]; then MINIMUM_SCORE=TOTAL; else MINIMUM_SCORE=$1; fi + if (( $SCORE < $MINIMUM_SCORE )); then echo "minimum score $MINIMUM_SCORE was not met!"; exit 1; fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a6add5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# Visual Studio Code related +.classpath +.project +.settings/ +.vscode/* + +# Idea related +*.iml +*.ipr +*.iws +.idea/ + +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build outputs. +build/ + +# Omit committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock + +# Ignore pubspec_overrides.yaml as local package paths may be different for everyone +pubspec_overrides.yaml + +# Test and Coverage generated outputs +coverage/ + +# # Generated dart files +# *.g.dart diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6b2161c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +## [1.0.0] - [Jan 15, 2023] +* [Initial] Kubeconfig utility diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8d6d154 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Fatih Sever + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4737e7 --- /dev/null +++ b/README.md @@ -0,0 +1,89 @@ +[![Kubeconfig Logo][kubeconfig_logo]][kubeconfig_link] + +[![CI][ci_badge]][ci_link] +[![Coverage][coverage_badge]][coverage_link] +[![License: MIT][license_badge]][license_link] +[![pub][pub_badge]][pub_link] +[![npm][npm_badge]][npm_link] + +--- +A library that simplifies the management of kubeconfig files. It offers a bunch of features, such as validating, merging, and converting kubeconfig files, to ensure that you have a consistent and optimized configuration for accessing multiple Kubernetes clusters. + +Developed with 💙 by [Fatih Sever][fatihsever_link] + +## Features ✨ +- **Validate**: Check the syntax and structure of kubeconfig files for common errors or inconsistencies. +- **Convert**: Convert between different formats (YAML to JSON or JSON to YAML). +- **Merge**: Combine multiple kubeconfig files into a single file, preserving context and cluster information, and avoiding duplication. + +## Documentation 📝 +Please visit the [official documentation][docs_link]. + +## Installation 💻 +### From pub: +For quick start, please include the following in pubspec.yaml +```yaml +dependencies: + kubeconfig: 1.0.0+1 +``` +For more information, please visit the [pub.dev](https://pub.dev/packages/kubeconfig/install) + +### From npm: +`kubeconfig` compiled to JavaScript, as an npm package. You can add it to your project using the command below. +```bash +npm install --save kubeconfig +``` + +For more information, please visit the [npmjs.com](https://www.npmjs.com/package/kubeconfig) + +## Quick Start 🚀 + +Validating a kubeconfig file: + +### Dart: +```dart +import 'dart:io'; +import 'package:kubeconfig/kubeconfig.dart'; + +void main() { + final kubeconfigYaml = await File('kube/config.yaml').readAsString(); + final kubeconfig = Kubeconfig.fromYaml(kubeconfigYaml); + final validationResult = kubeconfig.validate(); +} +``` + +### JavaScript: +```javascript +import { readFileSync } from 'fs'; +import { Kubeconfig } from './kubeconfig'; + +let kubeconfigYaml = readFileSync('kube/config.yaml'); +let kubeconfig = Kubeconfig.fromYaml(kubeconfigYaml); +let validationResult = kubeconfig.validate(); +``` + +## Examples 📋 +### Dart: +- **Validate**: [example/dart/validate.dart](example/validate.dart) +- **Convert**: [example/dart/convert.dart](example/convert.dart) +- **Merge**: [example/dart/merge.dart](example/merge.dart) + +### Javascript: +- **Validate**: [example/js/validate.js](example/validate.js) +- **Convert**: [example/js/validate.js](example/validate.js) +- **Merge**: [example/js/validate.js](example/validate.js) + +[kubeconfig_logo]: assets/logo.svg +[kubeconfig_link]: https://fatihsever.github.io/kubeconfig-lib/ +[ci_badge]: https://github.com/fatihsever/kubeconfig-lib/actions/workflows/ci.yml/badge.svg?branch=main +[ci_link]: https://github.com/fatihsever/kubeconfig-lib/actions/workflows/ci.yml +[coverage_badge]: https://codecov.io/github/fatihsever/kubeconfig-lib/badges/coverage.svg?branch=main +[coverage_link]: https://codecov.io/github/fatihsever/kubeconfig-lib/badges?branch=master +[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg +[license_link]: https://opensource.org/licenses/MIT +[pub_badge]: https://img.shields.io/pub/v/kubeconfig +[pub_link]: https://pub.dev/packages/kubeconfig +[npm_badge]: https://img.shields.io/npm/v/kubeconfig +[npm_link]: https://www.npmjs.com/package/kubeconfig +[fatihsever_link]: https://fatihsever.com/ +[docs_link]: https://fatihsever.github.io/kubeconfig-lib/ diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..b5d965b --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:very_good_analysis/analysis_options.5.0.0.yaml +analyzer: + exclude: + - "**/*.g.dart" diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 0000000..57c779c --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/logo.webp b/assets/logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..ae713b94115ff4b73cfb764d93b8671526beca35 GIT binary patch literal 4444 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 literal 0 HcmV?d00001 diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..b6925d8 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,11 @@ +.yarn/ +.next/ +node_modules/ +dist/ + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +.pnp.* diff --git a/docs/components/logo.js b/docs/components/logo.js new file mode 100644 index 0000000..2fe67ad --- /dev/null +++ b/docs/components/logo.js @@ -0,0 +1,18 @@ +export default function Logo({ height }) { + return ( + + + + + ); +} diff --git a/docs/next.config.js b/docs/next.config.js new file mode 100644 index 0000000..c66441a --- /dev/null +++ b/docs/next.config.js @@ -0,0 +1,16 @@ +const withNextra = require("nextra")({ + theme: "nextra-theme-docs", + themeConfig: "./theme.config.js", +}); + +module.exports = withNextra({ + redirects: () => { + return [ + { + source: "/", + destination: "/getting-started", + permanent: true, + }, + ]; + }, +}); diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..7bf6b22 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,19 @@ +{ + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "next": "^14.0.4", + "nextra": "^2.13.2", + "nextra-theme-docs": "^2.13.2", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "autoprefixer": "^10.4.16", + "postcss": "^8.4.33", + "tailwindcss": "^3.4.1" + } +} diff --git a/docs/pages/_app.mdx b/docs/pages/_app.mdx new file mode 100644 index 0000000..048541e --- /dev/null +++ b/docs/pages/_app.mdx @@ -0,0 +1,5 @@ +import '../styles/globals.css' + +export default function App({ Component, pageProps }) { + return +} diff --git a/docs/pages/getting-started.mdx b/docs/pages/getting-started.mdx new file mode 100644 index 0000000..bad5562 --- /dev/null +++ b/docs/pages/getting-started.mdx @@ -0,0 +1 @@ +# Getting Started diff --git a/docs/postcss.config.js b/docs/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/docs/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/docs/public/favicon/android-chrome-192x192.png b/docs/public/favicon/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..d42e5a943052662c38e2c3a504ac1d68efb81687 GIT binary patch literal 14296 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 E0FJHLEC2ui literal 0 HcmV?d00001 diff --git a/docs/public/favicon/android-chrome-512x512.png b/docs/public/favicon/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..8776d0e6229ebcee024fdf91f947a7a3e0b0990d GIT binary patch literal 39535 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 b3cpckxRIpmr=5KqAmGo`(A=O#&n@nM2!NWl literal 0 HcmV?d00001 diff --git a/docs/public/favicon/apple-touch-icon.png b/docs/public/favicon/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8e53adda8a4f7428b8e2c70e98d9fe6f98090735 GIT binary patch literal 12885 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 literal 0 HcmV?d00001 diff --git a/docs/public/favicon/favicon-16x16.png b/docs/public/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..fa49bb8b2c43466914dd386e7e5a5523150ad1d0 GIT binary patch literal 799 zcmV+)1K|9LP)Px%*-1n}R5(vaTLbCnQ?b#b$8u$yC@Yx8f8M78Di1}O-h3dDlDSH#I>NP zUVO=rq9XHU?Sc|y(LL}X%j}{rW}+plk&=Q6re>MruI;WnJL}F&&3|;F=4j@W0?tSngBSDA6SS{*5^C){VMILQl zqeb-@E0k7_0Rbs-I?%MrBLF2)`p|`U4nGVmg@aoo@ZP~=%qfy0qn^U?od*1Nil}Y% zAvaZzOGnM1sab%_Djh?HZ`99AxZmi-oq7)h`9svofG|*}&GU4~(8C1RTkV%zDTdM`t zIUvZ2zS>VdY+0{ETud0oCPn=C6U5m(6FK4js}raww4mv$A5OQ3w!Q$YMjAQ)&lxh( zt=AqrX!Js_rC_&Npwm#eQR_x#GK=__Ff!HUXMag&TaE$6v(6*{C0S_aFg&5&dub#M zyDbVHUV=31jnh?5NRleQ537m6i;vUr32J*~qRb=~b?rR-0U24zEXoTkpysTs z6e*ClUI7`2Eb(|z=>)$3e2W+n@B^b2V16>w^g5gLY?mk^qL!AE7CoBU8=42AL& d7IMzT;vaOiRjdzBU|j$J002ovPDHLkV1gprU~d2b literal 0 HcmV?d00001 diff --git a/docs/public/favicon/favicon-32x32.png b/docs/public/favicon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..fdc87b658c8701bbe04e18ca9842d94a64d6a967 GIT binary patch literal 1801 zcmV+k2ln`hP)Px*!%0LzR9Hu?S7%UER}}ut0#2-;5hEJ0 zBsMfLN^FQCHqcRn8XYw#V8zK8HI}GY5(`*ifd#g>EL&c3FGG2}1;ph1+qd`L^WAg4 zbIx}emStHq&|VsxNIYpmiNysM3kU=Zn(2fHAEJa*%rxjU=1l-B*j0qIYo$C#3qSS3 zC-2Mu9{>&~i^q8mv}z=RNXWfa#3lnS-M8@^O&_YnmmewqI{=f_g|9Xna4Xx6ciKp> zZi*TTnV|CE$?FSo?O_?u(X_z|Odh1H{BC!$*p*>{&F;d)flA0E{PgfrV79tIZkYAN zUU^V(D={`t*V2fjUa{inrB^Up`PAtWAi>;GDzt4PhSS9&dPgzN+$>KOxyXiT8px$w z5F7wb7Z4s-h^r6yxAWHu@uJXKZ+IC7c(1*b-uBcDE>F4!NU$MX!yzgMKvqr}LSqZ- zbyBflQ-lWbznYMhQx&cHHjnKk$GkCKmCHB)NO_Hn(ZlYj@0jxcQ|9~N`;-z~cf*I; zPUzf5g2YIzdjRBX+EptS?JkDPRW}HM0N6iIht&s-xbinYWwq^IJl+e#yH}N}+ddHc zixGRzSs)Yu!7U}Y{;1pm$?u>pGK}acLvSkzBq9c+jXlbBAmf@9d(T^7DJ>_bRwaN~ z$RM|BMl$bb>Tc&OSOo%POtsFaiyaYJ7zy~|h%{cPA6)VHM(IZfbBC`uOAD5v| zkOwZ`x1qVO2#wW3>TLebA{1L(*gQjvluQefPFpCTR*gmUteVCHK*}$4O+n>4UvB|^ zn4m`c=3;uI?dfK0PczdS9$(^%sKg>~#eo?;xoY(-#G zG1g2{!%tHliD66iJRVINsG#$rx-t9Cnc3BcjI}aOBm`2I`r?Jb37twvL%l!Kf~;&i zV#2)XP$Ix0hAJTxFgSC=iUFNvh)Oiz+%0aqCQV4A5Kt~P^ATbB7v5kJQjKiF33IIg zNO#*hQ;S&%2Hbz_hHGdlMz6@P z6Tr;j%K8C(-q#afk5FQIyaBy~JkYy?6isv@{PoO^&weaG=!c$&3{k;S>cVe#Y`BnR zL;p@5c&n)xLl*1n1TbTm63otY6T9)4iMOz+R)}^@#TeH|jxGVx%Kz;SmWmJ}JnlZR zqqQFy*PuL5$*U$NNy&B6w=^+OZ9~E}#o(&Q423nfk+exuJ)SJ!+(kps(lp-P3jMP84 zB}w*1k5Pfw2i6=iV&D1l=22nmr>fD~PmHlE^I>=L~v9$QuDj#=%@;cJ7&Vq z(LTtyZpHjv#poC8LF+&MxCwd1PAnPkP3OtNWPSxCMd{G7MU6&OQxlTj98ePg3L|VK8ci9yxj^DF!6Z(a}mEydYsGge8%xZXH^PksPJt@qm{C(qz^gG{T)! z?$lb0#7G?k3?ZG1&IBSnG%6tla`CQ>rlqEH;*}6CtUq5basZ@Vv(n~Kn@}gIhzr-? zr^80tdI{;u9Ap~Wp;ZcL6r#2jxh*{s9m1tkgocXIZE5_@ zDG`BoKmx#>q$AE0G6qM!^`*_M!Z-kG)B6>RLwd+?_NEQSSMJqH-yjb>%(dfbe(l9Qyq}&1^2T$HmhzBpY)396vIO!~S9aG5}7+>*OL@HqWEG_4q!6RXT(TS-W4YYd^ zBMLWmk{V(WLrF%;@cwhY2$e}0^!rz!4DKdFU^6i-Wg_D%EWlrcEi<&7@bfrOv6!%X z{ShNPWdh3H>hHZx$4uCf!RJ8FKq=xPG?fnXOPmOgGf)u3IeAxTlvTNRn}XK~FA*%yJ6jo463GYGj#sK!5wP5XGzJU3-s|+!r-mh~9&YA|ljtNm$ r9Wdghp?t!T2IS=_pfiAo(}vnV=g=ojXp_;|00000NkvXXu0mjfc~(Nd literal 0 HcmV?d00001 diff --git a/docs/public/favicon/favicon.ico b/docs/public/favicon/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8a376b28d62a7ab62781d401b6718d70253e2fc8 GIT binary patch literal 15406 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 { + return ( + <> + + + Kubeconfig Library + + + ); + }, + project: { + link: "https://github.com/fatihsever/kubeconfig-lib", + }, +}; diff --git a/docs/yarn.lock b/docs/yarn.lock new file mode 100644 index 0000000..52ccc9a --- /dev/null +++ b/docs/yarn.lock @@ -0,0 +1,5278 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 8 + cacheKey: 10c0 + +"@alloc/quick-lru@npm:^5.2.0": + version: 5.2.0 + resolution: "@alloc/quick-lru@npm:5.2.0" + checksum: 7b878c48b9d25277d0e1a9b8b2f2312a314af806b4129dc902f2bc29ab09b58236e53964689feec187b28c80d2203aff03829754773a707a8a5987f1b7682d92 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.12.5": + version: 7.23.8 + resolution: "@babel/runtime@npm:7.23.8" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: ba5e8fbb32ef04f6cab5e89c54a0497c2fde7b730595cc1af93496270314f13ff2c6a9360fdb2f0bdd4d6b376752ce3cf85642bd6b876969a6a62954934c2df8 + languageName: node + linkType: hard + +"@braintree/sanitize-url@npm:^6.0.1": + version: 6.0.4 + resolution: "@braintree/sanitize-url@npm:6.0.4" + checksum: 5d7bac57f3e49931db83f65aaa4fd22f96caa323bf0c7fcf6851fdbed179a8cf29eaa5dd372d340fc51ca5f44345ea5bc0196b36c8b16179888a7c9044313420 + languageName: node + linkType: hard + +"@headlessui/react@npm:^1.7.10": + version: 1.7.18 + resolution: "@headlessui/react@npm:1.7.18" + dependencies: + "@tanstack/react-virtual": "npm:^3.0.0-beta.60" + client-only: "npm:^0.0.1" + peerDependencies: + react: ^16 || ^17 || ^18 + react-dom: ^16 || ^17 || ^18 + checksum: 2d88d10874879182d4b9ed9a7779266032214034481129ba544e858d3624c8d12333e6a9d9d8263f2f116bc823bcfd43a2d1f69800fbf6a47b34d989370346e5 + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: "npm:^5.1.2" + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: "npm:^7.0.1" + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: "npm:^8.1.0" + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.3 + resolution: "@jridgewell/gen-mapping@npm:0.3.3" + dependencies: + "@jridgewell/set-array": "npm:^1.0.1" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + "@jridgewell/trace-mapping": "npm:^0.3.9" + checksum: 376fc11cf5a967318ba3ddd9d8e91be528eab6af66810a713c49b0c3f8dc67e9949452c51c38ab1b19aa618fb5e8594da5a249977e26b1e7fea1ee5a1fcacc74 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.1 + resolution: "@jridgewell/resolve-uri@npm:3.1.1" + checksum: 0dbc9e29bc640bbbdc5b9876d2859c69042bfcf1423c1e6421bcca53e826660bff4e41c7d4bcb8dbea696404231a6f902f76ba41835d049e20f2dd6cffb713bf + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.0.1": + version: 1.1.2 + resolution: "@jridgewell/set-array@npm:1.1.2" + checksum: bc7ab4c4c00470de4e7562ecac3c0c84f53e7ee8a711e546d67c47da7febe7c45cd67d4d84ee3c9b2c05ae8e872656cdded8a707a283d30bd54fbc65aef821ab + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: 0c6b5ae663087558039052a626d2d7ed5208da36cfd707dcc5cea4a07cfc918248403dcb5989a8f7afaf245ce0573b7cc6fd94c4a30453bd10e44d9363940ba5 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.21 + resolution: "@jridgewell/trace-mapping@npm:0.3.21" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 4ae1c862ca0a12e1fb08ee48bb2fd65667a5258a97cc37a8708ff1e1d6a351e6a1166f2f806a9d9b9680f841da9fbde35fe6bd971eee3bdf1c10ea669ba5707a + languageName: node + linkType: hard + +"@mdx-js/mdx@npm:^2.2.1, @mdx-js/mdx@npm:^2.3.0": + version: 2.3.0 + resolution: "@mdx-js/mdx@npm:2.3.0" + dependencies: + "@types/estree-jsx": "npm:^1.0.0" + "@types/mdx": "npm:^2.0.0" + estree-util-build-jsx: "npm:^2.0.0" + estree-util-is-identifier-name: "npm:^2.0.0" + estree-util-to-js: "npm:^1.1.0" + estree-walker: "npm:^3.0.0" + hast-util-to-estree: "npm:^2.0.0" + markdown-extensions: "npm:^1.0.0" + periscopic: "npm:^3.0.0" + remark-mdx: "npm:^2.0.0" + remark-parse: "npm:^10.0.0" + remark-rehype: "npm:^10.0.0" + unified: "npm:^10.0.0" + unist-util-position-from-estree: "npm:^1.0.0" + unist-util-stringify-position: "npm:^3.0.0" + unist-util-visit: "npm:^4.0.0" + vfile: "npm:^5.0.0" + checksum: 719384d8e72abd3e83aa2fd3010394636e32cc0e5e286b6414427ef03121397586ce97ec816afcc4d2b22ba65939c3801a8198e04cf921dd597c0aa9fd75dbb4 + languageName: node + linkType: hard + +"@mdx-js/react@npm:^2.2.1, @mdx-js/react@npm:^2.3.0": + version: 2.3.0 + resolution: "@mdx-js/react@npm:2.3.0" + dependencies: + "@types/mdx": "npm:^2.0.0" + "@types/react": "npm:>=16" + peerDependencies: + react: ">=16" + checksum: 6d647115703dbe258f7fe372499fa8c6fe17a053ff0f2a208111c9973a71ae738a0ed376770445d39194d217e00e1a015644b24f32c2f7cb4f57988de0649b15 + languageName: node + linkType: hard + +"@napi-rs/simple-git-android-arm-eabi@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-android-arm-eabi@npm:0.1.9" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@napi-rs/simple-git-android-arm64@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-android-arm64@npm:0.1.9" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@napi-rs/simple-git-darwin-arm64@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-darwin-arm64@npm:0.1.9" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@napi-rs/simple-git-darwin-x64@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-darwin-x64@npm:0.1.9" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@napi-rs/simple-git-linux-arm-gnueabihf@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-linux-arm-gnueabihf@npm:0.1.9" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@napi-rs/simple-git-linux-arm64-gnu@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-linux-arm64-gnu@npm:0.1.9" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@napi-rs/simple-git-linux-arm64-musl@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-linux-arm64-musl@npm:0.1.9" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@napi-rs/simple-git-linux-x64-gnu@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-linux-x64-gnu@npm:0.1.9" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@napi-rs/simple-git-linux-x64-musl@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-linux-x64-musl@npm:0.1.9" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@napi-rs/simple-git-win32-arm64-msvc@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-win32-arm64-msvc@npm:0.1.9" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@napi-rs/simple-git-win32-x64-msvc@npm:0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git-win32-x64-msvc@npm:0.1.9" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@napi-rs/simple-git@npm:^0.1.9": + version: 0.1.9 + resolution: "@napi-rs/simple-git@npm:0.1.9" + dependencies: + "@napi-rs/simple-git-android-arm-eabi": "npm:0.1.9" + "@napi-rs/simple-git-android-arm64": "npm:0.1.9" + "@napi-rs/simple-git-darwin-arm64": "npm:0.1.9" + "@napi-rs/simple-git-darwin-x64": "npm:0.1.9" + "@napi-rs/simple-git-linux-arm-gnueabihf": "npm:0.1.9" + "@napi-rs/simple-git-linux-arm64-gnu": "npm:0.1.9" + "@napi-rs/simple-git-linux-arm64-musl": "npm:0.1.9" + "@napi-rs/simple-git-linux-x64-gnu": "npm:0.1.9" + "@napi-rs/simple-git-linux-x64-musl": "npm:0.1.9" + "@napi-rs/simple-git-win32-arm64-msvc": "npm:0.1.9" + "@napi-rs/simple-git-win32-x64-msvc": "npm:0.1.9" + dependenciesMeta: + "@napi-rs/simple-git-android-arm-eabi": + optional: true + "@napi-rs/simple-git-android-arm64": + optional: true + "@napi-rs/simple-git-darwin-arm64": + optional: true + "@napi-rs/simple-git-darwin-x64": + optional: true + "@napi-rs/simple-git-linux-arm-gnueabihf": + optional: true + "@napi-rs/simple-git-linux-arm64-gnu": + optional: true + "@napi-rs/simple-git-linux-arm64-musl": + optional: true + "@napi-rs/simple-git-linux-x64-gnu": + optional: true + "@napi-rs/simple-git-linux-x64-musl": + optional: true + "@napi-rs/simple-git-win32-arm64-msvc": + optional: true + "@napi-rs/simple-git-win32-x64-msvc": + optional: true + checksum: fcdaa2afa3ff8391cf12bc8ff292b2c503aa1b7ebd61774223408d7608409a26f2cc602a44d79ccfc4efa200257dbb29d81350a3f8307ef1cba9e212a4b3988e + languageName: node + linkType: hard + +"@next/env@npm:14.0.4": + version: 14.0.4 + resolution: "@next/env@npm:14.0.4" + checksum: 59b893d30aea0556379a24f6e4eac830677feb149bd8416b72383ea2600ce194fa22a79b2dd86e0b295c4a8f0702e461f48edaff1ac9173eddef42a4cce7fd98 + languageName: node + linkType: hard + +"@next/swc-darwin-arm64@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-darwin-arm64@npm:14.0.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@next/swc-darwin-x64@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-darwin-x64@npm:14.0.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@next/swc-linux-arm64-gnu@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-linux-arm64-gnu@npm:14.0.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@next/swc-linux-arm64-musl@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-linux-arm64-musl@npm:14.0.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@next/swc-linux-x64-gnu@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-linux-x64-gnu@npm:14.0.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@next/swc-linux-x64-musl@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-linux-x64-musl@npm:14.0.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@next/swc-win32-arm64-msvc@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-win32-arm64-msvc@npm:14.0.4" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@next/swc-win32-ia32-msvc@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-win32-ia32-msvc@npm:14.0.4" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@next/swc-win32-x64-msvc@npm:14.0.4": + version: 14.0.4 + resolution: "@next/swc-win32-x64-msvc@npm:14.0.4" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@nodelib/fs.scandir@npm:2.1.5": + version: 2.1.5 + resolution: "@nodelib/fs.scandir@npm:2.1.5" + dependencies: + "@nodelib/fs.stat": "npm:2.0.5" + run-parallel: "npm:^1.1.9" + checksum: 732c3b6d1b1e967440e65f284bd06e5821fedf10a1bea9ed2bb75956ea1f30e08c44d3def9d6a230666574edbaf136f8cfd319c14fd1f87c66e6a44449afb2eb + languageName: node + linkType: hard + +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: 88dafe5e3e29a388b07264680dc996c17f4bda48d163a9d4f5c1112979f0ce8ec72aa7116122c350b4e7976bc5566dc3ddb579be1ceaacc727872eb4ed93926d + languageName: node + linkType: hard + +"@nodelib/fs.walk@npm:^1.2.3": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": "npm:2.1.5" + fastq: "npm:^1.6.0" + checksum: db9de047c3bb9b51f9335a7bb46f4fcfb6829fb628318c12115fbaf7d369bfce71c15b103d1fc3b464812d936220ee9bc1c8f762d032c9f6be9acc99249095b1 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.1" + checksum: 7b89590598476dda88e79c473766b67c682aae6e0ab0213491daa6083dcc0c171f86b3868f5506f22c09aa5ea69ad7dfb78f4bf39a8dca375d89a42f408645b3 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.0 + resolution: "@npmcli/fs@npm:3.1.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 162b4a0b8705cd6f5c2470b851d1dc6cd228c86d2170e1769d738c1fbb69a87160901411c3c035331e9e99db72f1f1099a8b734bf1637cc32b9a5be1660e4e1e + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd + languageName: node + linkType: hard + +"@popperjs/core@npm:^2.11.6": + version: 2.11.8 + resolution: "@popperjs/core@npm:2.11.8" + checksum: 4681e682abc006d25eb380d0cf3efc7557043f53b6aea7a5057d0d1e7df849a00e281cd8ea79c902a35a414d7919621fc2ba293ecec05f413598e0b23d5a1e63 + languageName: node + linkType: hard + +"@swc/helpers@npm:0.5.2": + version: 0.5.2 + resolution: "@swc/helpers@npm:0.5.2" + dependencies: + tslib: "npm:^2.4.0" + checksum: b6fa49bcf6c00571d0eb7837b163f8609960d4d77538160585e27ed167361e9776bd6e5eb9646ffac2fb4d43c58df9ca50dab9d96ab097e6591bc82a75fd1164 + languageName: node + linkType: hard + +"@tanstack/react-virtual@npm:^3.0.0-beta.60": + version: 3.0.1 + resolution: "@tanstack/react-virtual@npm:3.0.1" + dependencies: + "@tanstack/virtual-core": "npm:3.0.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 2b9464dab8a975734b651211402a4eaf10e4ae6d9570138576891db350cfabe11e444fea8f17ef0b26ef8ede0adc230bec9c8fe859e61ca66147831076b77bb2 + languageName: node + linkType: hard + +"@tanstack/virtual-core@npm:3.0.0": + version: 3.0.0 + resolution: "@tanstack/virtual-core@npm:3.0.0" + checksum: d0899fe470b43f80a2ccc567a01138cc015900f13d91b82abc784fc7bc46419e9c8b99c102a5c6ee76d15933db61aecc68c0ae8e92e9cb9ded9ae2f51a01cf4c + languageName: node + linkType: hard + +"@theguild/remark-mermaid@npm:^0.0.5": + version: 0.0.5 + resolution: "@theguild/remark-mermaid@npm:0.0.5" + dependencies: + mermaid: "npm:^10.2.2" + unist-util-visit: "npm:^5.0.0" + peerDependencies: + react: ^18.2.0 + checksum: 3471a32a87d50f7eb699f15ff181f9a3698209951ef0fab1e928ea391275105286b0391e46cca4dd22d30dcab934e5c7eb6573c341f5d8543ca5bcb2f60cc916 + languageName: node + linkType: hard + +"@theguild/remark-npm2yarn@npm:^0.2.0": + version: 0.2.1 + resolution: "@theguild/remark-npm2yarn@npm:0.2.1" + dependencies: + npm-to-yarn: "npm:^2.1.0" + unist-util-visit: "npm:^5.0.0" + checksum: 69380ac3814bcf2f9c00c8e375d97e55220adea04d9c887df1b6ac888b726a8a7aaf391ed80ceca1756cfa39d572221d12f681bc1a5f3fdf49a0ed59f7c3addc + languageName: node + linkType: hard + +"@types/acorn@npm:^4.0.0": + version: 4.0.6 + resolution: "@types/acorn@npm:4.0.6" + dependencies: + "@types/estree": "npm:*" + checksum: 5a65a1d7e91fc95703f0a717897be60fa7ccd34b17f5462056274a246e6690259fe0a1baabc86fd3260354f87245cb3dc483346d7faad2b78fc199763978ede9 + languageName: node + linkType: hard + +"@types/d3-scale-chromatic@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/d3-scale-chromatic@npm:3.0.3" + checksum: 2f48c6f370edba485b57b73573884ded71914222a4580140ff87ee96e1d55ccd05b1d457f726e234a31269b803270ac95d5554229ab6c43c7e4a9894e20dd490 + languageName: node + linkType: hard + +"@types/d3-scale@npm:^4.0.3": + version: 4.0.8 + resolution: "@types/d3-scale@npm:4.0.8" + dependencies: + "@types/d3-time": "npm:*" + checksum: 57de90e4016f640b83cb960b7e3a0ab3ed02e720898840ddc5105264ffcfea73336161442fdc91895377c2d2f91904d637282f16852b8535b77e15a761c8e99e + languageName: node + linkType: hard + +"@types/d3-time@npm:*": + version: 3.0.3 + resolution: "@types/d3-time@npm:3.0.3" + checksum: 245a8aadca504df27edf730de502e47a68f16ae795c86b5ca35e7afa91c133aa9ef4d08778f8cf1ed2be732f89a4105ba4b437ce2afbdfd17d3d937b6ba5f568 + languageName: node + linkType: hard + +"@types/debug@npm:^4.0.0": + version: 4.1.12 + resolution: "@types/debug@npm:4.1.12" + dependencies: + "@types/ms": "npm:*" + checksum: 5dcd465edbb5a7f226e9a5efd1f399c6172407ef5840686b73e3608ce135eeca54ae8037dcd9f16bdb2768ac74925b820a8b9ecc588a58ca09eca6acabe33e2f + languageName: node + linkType: hard + +"@types/estree-jsx@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/estree-jsx@npm:1.0.3" + dependencies: + "@types/estree": "npm:*" + checksum: 41742a7b0874f63e61396d87a46d3ca531850a0e2cd7cec304339b8df439b6371d5e8758f34de9b5d9e940486ea21305b2f74cb420754838ecdfdaba918afc66 + languageName: node + linkType: hard + +"@types/estree@npm:*, @types/estree@npm:^1.0.0": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d + languageName: node + linkType: hard + +"@types/hast@npm:^2.0.0": + version: 2.3.9 + resolution: "@types/hast@npm:2.3.9" + dependencies: + "@types/unist": "npm:^2" + checksum: 8660bd1ed2cd91ad4721c9d02ce88991e0950b07826bd5a85cde9e76fa226a47174f53c6d03e0a54b4668e5780fbdc352ae390a11c807e3c7d08c0f04d046259 + languageName: node + linkType: hard + +"@types/hast@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/hast@npm:3.0.3" + dependencies: + "@types/unist": "npm:*" + checksum: 0779740926efc1f856976abd95fcb04f4b45d885ec65ef148505722e15cd8fdf4e84d93bf29908131ae6b040f3ca1c1f0cf9fef1b35d52c90c76ff90cfc1214f + languageName: node + linkType: hard + +"@types/js-yaml@npm:^4.0.0": + version: 4.0.9 + resolution: "@types/js-yaml@npm:4.0.9" + checksum: 24de857aa8d61526bbfbbaa383aa538283ad17363fcd5bb5148e2c7f604547db36646440e739d78241ed008702a8920665d1add5618687b6743858fae00da211 + languageName: node + linkType: hard + +"@types/katex@npm:^0.16.0": + version: 0.16.7 + resolution: "@types/katex@npm:0.16.7" + checksum: 68dcb9f68a90513ec78ca0196a142e15c2a2c270b1520d752bafd47a99207115085a64087b50140359017d7e9c870b3c68e7e4d36668c9e348a9ef0c48919b5a + languageName: node + linkType: hard + +"@types/mdast@npm:^3.0.0": + version: 3.0.15 + resolution: "@types/mdast@npm:3.0.15" + dependencies: + "@types/unist": "npm:^2" + checksum: fcbf716c03d1ed5465deca60862e9691414f9c43597c288c7d2aefbe274552e1bbd7aeee91b88a02597e88a28c139c57863d0126fcf8416a95fdc681d054ee3d + languageName: node + linkType: hard + +"@types/mdast@npm:^4.0.0": + version: 4.0.3 + resolution: "@types/mdast@npm:4.0.3" + dependencies: + "@types/unist": "npm:*" + checksum: e6994404f5ce58073aa6c1a37ceac3060326470a464e2d751580a9f89e2dbca3a2a6222b849bdaaa5bffbe89033c50a886d17e49fca3b040a4ffcf970e387a0c + languageName: node + linkType: hard + +"@types/mdx@npm:^2.0.0": + version: 2.0.10 + resolution: "@types/mdx@npm:2.0.10" + checksum: a2a5d71967c44c650e883eaaeb61db9c0758b9c1d675e04b7a3cfeeaee6efd5044dc9c78d780aa3fe408a2f85680bf3b723c92a1772bb6c2da35ef346d766de2 + languageName: node + linkType: hard + +"@types/ms@npm:*": + version: 0.7.34 + resolution: "@types/ms@npm:0.7.34" + checksum: ac80bd90012116ceb2d188fde62d96830ca847823e8ca71255616bc73991aa7d9f057b8bfab79e8ee44ffefb031ddd1bcce63ea82f9e66f7c31ec02d2d823ccc + languageName: node + linkType: hard + +"@types/prop-types@npm:*": + version: 15.7.11 + resolution: "@types/prop-types@npm:15.7.11" + checksum: e53423cf9d510515ef8b47ff42f4f1b65a7b7b37c8704e2dbfcb9a60defe0c0e1f3cb1acfdeb466bad44ca938d7c79bffdd51b48ffb659df2432169d0b27a132 + languageName: node + linkType: hard + +"@types/react@npm:>=16": + version: 18.2.48 + resolution: "@types/react@npm:18.2.48" + dependencies: + "@types/prop-types": "npm:*" + "@types/scheduler": "npm:*" + csstype: "npm:^3.0.2" + checksum: 7e89f18ea2928b1638f564b156d692894dcb9352a7e0a807873c97e858abe1f23dbd165a25dd088a991344e973fdeef88ba5724bfb64504b74072cbc9c220c3a + languageName: node + linkType: hard + +"@types/scheduler@npm:*": + version: 0.16.8 + resolution: "@types/scheduler@npm:0.16.8" + checksum: f86de504945b8fc41b1f391f847444d542e2e4067cf7e5d9bfeb5d2d2393d3203b1161bc0ef3b1e104d828dabfb60baf06e8d2c27e27ff7e8258e6e618d8c4ec + languageName: node + linkType: hard + +"@types/unist@npm:*, @types/unist@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/unist@npm:3.0.2" + checksum: 39f220ce184a773c55c18a127062bfc4d0d30c987250cd59bab544d97be6cfec93717a49ef96e81f024b575718f798d4d329eb81c452fc57d6d051af8b043ebf + languageName: node + linkType: hard + +"@types/unist@npm:^2, @types/unist@npm:^2.0.0": + version: 2.0.10 + resolution: "@types/unist@npm:2.0.10" + checksum: 5f247dc2229944355209ad5c8e83cfe29419fa7f0a6d557421b1985a1500444719cc9efcc42c652b55aab63c931813c88033e0202c1ac684bcd4829d66e44731 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.0.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 8209c937cb39119f44eb63cf90c0b73e7c754209a6411c707be08e50e29ee81356dca1a848a405c8bdeebfe2f5e4f831ad310ae1689eeef65e7445c090c6657d + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.0.0": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 4c54868fbef3b8d58927d5e33f0a4de35f59012fe7b12cf9dfbb345fb8f46607709e1c4431be869a23fb63c151033d84c4198fa9f79385cec34fcb1dd53974c1 + languageName: node + linkType: hard + +"acorn@npm:^8.0.0": + version: 8.11.3 + resolution: "acorn@npm:8.11.3" + bin: + acorn: bin/acorn + checksum: 3ff155f8812e4a746fee8ecff1f227d527c4c45655bb1fad6347c3cb58e46190598217551b1500f18542d2bbe5c87120cb6927f5a074a59166fbdd9468f0a299 + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" + dependencies: + debug: "npm:^4.3.4" + checksum: fc974ab57ffdd8421a2bc339644d312a9cca320c20c3393c9d8b1fd91731b9bbabdb985df5fc860f5b79d81c3e350daa3fcb31c5c07c0bb385aafc817df004ce + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: "npm:^2.0.0" + indent-string: "npm:^4.0.0" + checksum: a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 + languageName: node + linkType: hard + +"ansi-sequence-parser@npm:^1.1.0": + version: 1.1.1 + resolution: "ansi-sequence-parser@npm:1.1.1" + checksum: ab2259ccf69f145ecf1418d4e71524158828f44afdf37c7536677871f4cebaa8b176fcb95de8f94a68129357dddc59586597da25f9d4ebf9968f6ef022bf0b31 + languageName: node + linkType: hard + +"ansi-styles@npm:^3.1.0": + version: 3.2.1 + resolution: "ansi-styles@npm:3.2.1" + dependencies: + color-convert: "npm:^1.9.0" + checksum: ece5a8ef069fcc5298f67e3f4771a663129abd174ea2dfa87923a2be2abf6cd367ef72ac87942da00ce85bd1d651d4cd8595aebdb1b385889b89b205860e977b + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: "npm:^2.0.1" + checksum: 895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: 5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c + languageName: node + linkType: hard + +"any-promise@npm:^1.0.0": + version: 1.3.0 + resolution: "any-promise@npm:1.3.0" + checksum: 60f0298ed34c74fef50daab88e8dab786036ed5a7fad02e012ab57e376e0a0b4b29e83b95ea9b5e7d89df762f5f25119b83e00706ecaccb22cfbacee98d74889 + languageName: node + linkType: hard + +"anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: "npm:^3.0.0" + picomatch: "npm:^2.0.4" + checksum: 57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac + languageName: node + linkType: hard + +"arch@npm:^2.1.0": + version: 2.2.0 + resolution: "arch@npm:2.2.0" + checksum: 4ceaf8d8207817c216ebc4469742052cb0a097bc45d9b7fcd60b7507220da545a28562ab5bdd4dfe87921bb56371a0805da4e10d704e01f93a15f83240f1284c + languageName: node + linkType: hard + +"arg@npm:1.0.0": + version: 1.0.0 + resolution: "arg@npm:1.0.0" + checksum: 10bbbda299b1a5d5f1cc6492bdea9413f148c36b58e7abc49e8b8337047eec5db154c1d2f99e942c4b777ae28215fc28506d303d7e30bcd80ca1ad7baeb6ce28 + languageName: node + linkType: hard + +"arg@npm:^5.0.2": + version: 5.0.2 + resolution: "arg@npm:5.0.2" + checksum: ccaf86f4e05d342af6666c569f844bec426595c567d32a8289715087825c2ca7edd8a3d204e4d2fb2aa4602e09a57d0c13ea8c9eea75aac3dbb4af5514e6800e + languageName: node + linkType: hard + +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: "npm:~1.0.2" + checksum: b2972c5c23c63df66bca144dbc65d180efa74f25f8fd9b7d9a0a6c88ae839db32df3d54770dcb6460cf840d232b60695d1a6b1053f599d84e73f7437087712de + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e + languageName: node + linkType: hard + +"astring@npm:^1.8.0": + version: 1.8.6 + resolution: "astring@npm:1.8.6" + bin: + astring: bin/astring + checksum: 31f09144597048c11072417959a412f208f8f95ba8dce408dfbc3367acb929f31fbcc00ed5eb61ccbf7c2f1173b9ac8bfcaaa37134a9455050c669b2b036ed88 + languageName: node + linkType: hard + +"autoprefixer@npm:^10.4.16": + version: 10.4.16 + resolution: "autoprefixer@npm:10.4.16" + dependencies: + browserslist: "npm:^4.21.10" + caniuse-lite: "npm:^1.0.30001538" + fraction.js: "npm:^4.3.6" + normalize-range: "npm:^0.1.2" + picocolors: "npm:^1.0.0" + postcss-value-parser: "npm:^4.2.0" + peerDependencies: + postcss: ^8.1.0 + bin: + autoprefixer: bin/autoprefixer + checksum: e00256e754d481a026d928bca729b25954074dd142dbec022f0a7db0d3bbc0dc2e2dc7542e94fec22eff81e21fe140e6856448e2d9a002660cb1e2ad434daee0 + languageName: node + linkType: hard + +"bail@npm:^2.0.0": + version: 2.0.2 + resolution: "bail@npm:2.0.2" + checksum: 25cbea309ef6a1f56214187004e8f34014eb015713ea01fa5b9b7e9e776ca88d0fdffd64143ac42dc91966c915a4b7b683411b56e14929fad16153fc026ffb8b + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee + languageName: node + linkType: hard + +"binary-extensions@npm:^2.0.0": + version: 2.2.0 + resolution: "binary-extensions@npm:2.2.0" + checksum: d73d8b897238a2d3ffa5f59c0241870043aa7471335e89ea5e1ff48edb7c2d0bb471517a3e4c5c3f4c043615caa2717b5f80a5e61e07503d51dc85cb848e665d + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: "npm:^1.0.0" + checksum: b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f + languageName: node + linkType: hard + +"braces@npm:^3.0.2, braces@npm:~3.0.2": + version: 3.0.2 + resolution: "braces@npm:3.0.2" + dependencies: + fill-range: "npm:^7.0.1" + checksum: 321b4d675791479293264019156ca322163f02dc06e3c4cab33bb15cd43d80b51efef69b0930cfde3acd63d126ebca24cd0544fa6f261e093a0fb41ab9dda381 + languageName: node + linkType: hard + +"browserslist@npm:^4.21.10": + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" + dependencies: + caniuse-lite: "npm:^1.0.30001565" + electron-to-chromium: "npm:^1.4.601" + node-releases: "npm:^2.0.14" + update-browserslist-db: "npm:^1.0.13" + bin: + browserslist: cli.js + checksum: 2a331aab90503130043ca41dd5d281fa1e89d5e076d07a2d75e76bf4d693bd56e73d5abcd8c4f39119da6328d450578c216cf1cd5c99b82d8a90a2ae6271b465 + languageName: node + linkType: hard + +"busboy@npm:1.6.0": + version: 1.6.0 + resolution: "busboy@npm:1.6.0" + dependencies: + streamsearch: "npm:^1.1.0" + checksum: fa7e836a2b82699b6e074393428b91ae579d4f9e21f5ac468e1b459a244341d722d2d22d10920cdd849743dbece6dca11d72de939fb75a7448825cf2babfba1f + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.2 + resolution: "cacache@npm:18.0.2" + dependencies: + "@npmcli/fs": "npm:^3.1.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^4.0.0" + ssri: "npm:^10.0.0" + tar: "npm:^6.1.11" + unique-filename: "npm:^3.0.0" + checksum: 7992665305cc251a984f4fdbab1449d50e88c635bc43bf2785530c61d239c61b349e5734461baa461caaee65f040ab14e2d58e694f479c0810cffd181ba5eabc + languageName: node + linkType: hard + +"camelcase-css@npm:^2.0.1": + version: 2.0.1 + resolution: "camelcase-css@npm:2.0.1" + checksum: 1a1a3137e8a781e6cbeaeab75634c60ffd8e27850de410c162cce222ea331cd1ba5364e8fb21c95e5ca76f52ac34b81a090925ca00a87221355746d049c6e273 + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001576 + resolution: "caniuse-lite@npm:1.0.30001576" + checksum: 79cf666f9139c542bdf75eab76171534dc638d2f8efacd325649c8ec6be59de400f0e9d6dc02504f12125626b306c0a848fe86904c01722218b2a479be82a9c1 + languageName: node + linkType: hard + +"ccount@npm:^2.0.0": + version: 2.0.1 + resolution: "ccount@npm:2.0.1" + checksum: 3939b1664390174484322bc3f45b798462e6c07ee6384cb3d645e0aa2f318502d174845198c1561930e1d431087f74cf1fe291ae9a4722821a9f4ba67e574350 + languageName: node + linkType: hard + +"chalk@npm:2.3.0": + version: 2.3.0 + resolution: "chalk@npm:2.3.0" + dependencies: + ansi-styles: "npm:^3.1.0" + escape-string-regexp: "npm:^1.0.5" + supports-color: "npm:^4.0.0" + checksum: ff3d14e7b31b1acdcd06b0c3b8d00e08748d76a0f2a6cc86baa1fe2456ebd4dd45037315a58df7f3c1886153c5d0a35da8183d2757f7fad28eaef6dedd33b437 + languageName: node + linkType: hard + +"character-entities-html4@npm:^2.0.0": + version: 2.1.0 + resolution: "character-entities-html4@npm:2.1.0" + checksum: fe61b553f083400c20c0b0fd65095df30a0b445d960f3bbf271536ae6c3ba676f39cb7af0b4bf2755812f08ab9b88f2feed68f9aebb73bb153f7a115fe5c6e40 + languageName: node + linkType: hard + +"character-entities-legacy@npm:^3.0.0": + version: 3.0.0 + resolution: "character-entities-legacy@npm:3.0.0" + checksum: ec4b430af873661aa754a896a2b55af089b4e938d3d010fad5219299a6b6d32ab175142699ee250640678cd64bdecd6db3c9af0b8759ab7b155d970d84c4c7d1 + languageName: node + linkType: hard + +"character-entities@npm:^2.0.0": + version: 2.0.2 + resolution: "character-entities@npm:2.0.2" + checksum: b0c645a45bcc90ff24f0e0140f4875a8436b8ef13b6bcd31ec02cfb2ca502b680362aa95386f7815bdc04b6464d48cf191210b3840d7c04241a149ede591a308 + languageName: node + linkType: hard + +"character-reference-invalid@npm:^2.0.0": + version: 2.0.1 + resolution: "character-reference-invalid@npm:2.0.1" + checksum: 2ae0dec770cd8659d7e8b0ce24392d83b4c2f0eb4a3395c955dce5528edd4cc030a794cfa06600fcdd700b3f2de2f9b8e40e309c0011c4180e3be64a0b42e6a1 + languageName: node + linkType: hard + +"chokidar@npm:^3.5.3": + version: 3.5.3 + resolution: "chokidar@npm:3.5.3" + dependencies: + anymatch: "npm:~3.1.2" + braces: "npm:~3.0.2" + fsevents: "npm:~2.3.2" + glob-parent: "npm:~5.1.2" + is-binary-path: "npm:~2.1.0" + is-glob: "npm:~4.0.1" + normalize-path: "npm:~3.0.0" + readdirp: "npm:~3.6.0" + dependenciesMeta: + fsevents: + optional: true + checksum: 1076953093e0707c882a92c66c0f56ba6187831aa51bb4de878c1fec59ae611a3bf02898f190efec8e77a086b8df61c2b2a3ea324642a0558bdf8ee6c5dc9ca1 + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: 594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 + languageName: node + linkType: hard + +"client-only@npm:0.0.1, client-only@npm:^0.0.1": + version: 0.0.1 + resolution: "client-only@npm:0.0.1" + checksum: 9d6cfd0c19e1c96a434605added99dff48482152af791ec4172fb912a71cff9027ff174efd8cdb2160cc7f377543e0537ffc462d4f279bc4701de3f2a3c4b358 + languageName: node + linkType: hard + +"clipboardy@npm:1.2.2": + version: 1.2.2 + resolution: "clipboardy@npm:1.2.2" + dependencies: + arch: "npm:^2.1.0" + execa: "npm:^0.8.0" + checksum: c343ee1ff74fd7202b8e549575e0e09d36d122cd06b078b171cf9ee37f03479d53547a5792ee879145841122c11ee4419078ffec07daf3eda4fa800758c8f1d9 + languageName: node + linkType: hard + +"clsx@npm:^2.0.0": + version: 2.1.0 + resolution: "clsx@npm:2.1.0" + checksum: c09c00ad14f638366ca814097e6cab533dfa1972a358da5b557be487168acbb25b4c1395e89ffa842a8a61ba87a462d2b4885bc9d4f8410b598f3cb339599cdb + languageName: node + linkType: hard + +"color-convert@npm:^1.9.0": + version: 1.9.3 + resolution: "color-convert@npm:1.9.3" + dependencies: + color-name: "npm:1.1.3" + checksum: 5ad3c534949a8c68fca8fbc6f09068f435f0ad290ab8b2f76841b9e6af7e0bb57b98cb05b0e19fe33f5d91e5a8611ad457e5f69e0a484caad1f7487fd0e8253c + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: "npm:~1.1.4" + checksum: 37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 + languageName: node + linkType: hard + +"color-name@npm:1.1.3": + version: 1.1.3 + resolution: "color-name@npm:1.1.3" + checksum: 566a3d42cca25b9b3cd5528cd7754b8e89c0eb646b7f214e8e2eaddb69994ac5f0557d9c175eb5d8f0ad73531140d9c47525085ee752a91a2ab15ab459caf6d6 + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 + languageName: node + linkType: hard + +"comma-separated-tokens@npm:^2.0.0": + version: 2.0.3 + resolution: "comma-separated-tokens@npm:2.0.3" + checksum: 91f90f1aae320f1755d6957ef0b864fe4f54737f3313bd95e0802686ee2ca38bff1dd381964d00ae5db42912dd1f4ae5c2709644e82706ffc6f6842a813cdd67 + languageName: node + linkType: hard + +"commander@npm:7": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a + languageName: node + linkType: hard + +"commander@npm:^4.0.0": + version: 4.1.1 + resolution: "commander@npm:4.1.1" + checksum: 84a76c08fe6cc08c9c93f62ac573d2907d8e79138999312c92d4155bc2325d487d64d13f669b2000c9f8caf70493c1be2dac74fec3c51d5a04f8bc3ae1830bab + languageName: node + linkType: hard + +"commander@npm:^8.3.0": + version: 8.3.0 + resolution: "commander@npm:8.3.0" + checksum: 8b043bb8322ea1c39664a1598a95e0495bfe4ca2fad0d84a92d7d1d8d213e2a155b441d2470c8e08de7c4a28cf2bc6e169211c49e1b21d9f7edc6ae4d9356060 + languageName: node + linkType: hard + +"compute-scroll-into-view@npm:^3.0.2": + version: 3.1.0 + resolution: "compute-scroll-into-view@npm:3.1.0" + checksum: bf305c4ece8e5c59ed3f7ed82b6dab5b7487ce26f56a693d903869964712870fccb08fe31d40edcbd600b03c99198f54d443acb315d674bd64fd344410c8672e + languageName: node + linkType: hard + +"cose-base@npm:^1.0.0": + version: 1.0.3 + resolution: "cose-base@npm:1.0.3" + dependencies: + layout-base: "npm:^1.0.0" + checksum: a6e400b1d101393d6af0967c1353355777c1106c40417c5acaef6ca8bdda41e2fc9398f466d6c85be30290943ad631f2590569f67b3fd5368a0d8318946bd24f + languageName: node + linkType: hard + +"cose-base@npm:^2.2.0": + version: 2.2.0 + resolution: "cose-base@npm:2.2.0" + dependencies: + layout-base: "npm:^2.0.0" + checksum: 14b9f8100ac322a00777ffb1daeb3321af368bbc9cabe3103943361273baee2003202ffe38e4ab770960b600214224e9c196195a78d589521540aa694df7cdec + languageName: node + linkType: hard + +"cross-spawn@npm:^5.0.1": + version: 5.1.0 + resolution: "cross-spawn@npm:5.1.0" + dependencies: + lru-cache: "npm:^4.0.1" + shebang-command: "npm:^1.2.0" + which: "npm:^1.2.9" + checksum: 1918621fddb9f8c61e02118b2dbf81f611ccd1544ceaca0d026525341832b8511ce2504c60f935dbc06b35e5ef156fe8c1e72708c27dd486f034e9c0e1e07201 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 + languageName: node + linkType: hard + +"cssesc@npm:^3.0.0": + version: 3.0.0 + resolution: "cssesc@npm:3.0.0" + bin: + cssesc: bin/cssesc + checksum: 6bcfd898662671be15ae7827120472c5667afb3d7429f1f917737f3bf84c4176003228131b643ae74543f17a394446247df090c597bb9a728cce298606ed0aa7 + languageName: node + linkType: hard + +"csstype@npm:^3.0.2": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248 + languageName: node + linkType: hard + +"cytoscape-cose-bilkent@npm:^4.1.0": + version: 4.1.0 + resolution: "cytoscape-cose-bilkent@npm:4.1.0" + dependencies: + cose-base: "npm:^1.0.0" + peerDependencies: + cytoscape: ^3.2.0 + checksum: 5e2480ddba9da1a68e700ed2c674cbfd51e9efdbd55788f1971a68de4eb30708e3b3a5e808bf5628f7a258680406bbe6586d87a9133e02a9bdc1ab1a92f512f2 + languageName: node + linkType: hard + +"cytoscape-fcose@npm:^2.1.0": + version: 2.2.0 + resolution: "cytoscape-fcose@npm:2.2.0" + dependencies: + cose-base: "npm:^2.2.0" + peerDependencies: + cytoscape: ^3.2.0 + checksum: ce472c9f85b9057e75c5685396f8e1f2468895e71b184913e05ad56dcf3092618fe59a1054f29cb0995051ba8ebe566ad0dd49a58d62845145624bd60cd44917 + languageName: node + linkType: hard + +"cytoscape@npm:^3.23.0": + version: 3.28.1 + resolution: "cytoscape@npm:3.28.1" + dependencies: + heap: "npm:^0.2.6" + lodash: "npm:^4.17.21" + checksum: eefe6c3f0253ffdca46f9857e06eba947cb863df0583eaf5bb112bc640425608b983847ee3a5b864f9833b80a9bc41a8dc5d675555b107a3321006edfff504ef + languageName: node + linkType: hard + +"d3-array@npm:1 - 2": + version: 2.12.1 + resolution: "d3-array@npm:2.12.1" + dependencies: + internmap: "npm:^1.0.0" + checksum: 7eca10427a9f113a4ca6a0f7301127cab26043fd5e362631ef5a0edd1c4b2dd70c56ed317566700c31e4a6d88b55f3951aaba192291817f243b730cb2352882e + languageName: node + linkType: hard + +"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.2.0": + version: 3.2.4 + resolution: "d3-array@npm:3.2.4" + dependencies: + internmap: "npm:1 - 2" + checksum: 08b95e91130f98c1375db0e0af718f4371ccacef7d5d257727fe74f79a24383e79aba280b9ffae655483ffbbad4fd1dec4ade0119d88c4749f388641c8bf8c50 + languageName: node + linkType: hard + +"d3-axis@npm:3": + version: 3.0.0 + resolution: "d3-axis@npm:3.0.0" + checksum: a271e70ba1966daa5aaf6a7f959ceca3e12997b43297e757c7b945db2e1ead3c6ee226f2abcfa22abbd4e2e28bd2b71a0911794c4e5b911bbba271328a582c78 + languageName: node + linkType: hard + +"d3-brush@npm:3": + version: 3.0.0 + resolution: "d3-brush@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-drag: "npm:2 - 3" + d3-interpolate: "npm:1 - 3" + d3-selection: "npm:3" + d3-transition: "npm:3" + checksum: 07baf00334c576da2f68a91fc0da5732c3a5fa19bd3d7aed7fd24d1d674a773f71a93e9687c154176f7246946194d77c48c2d8fed757f5dcb1a4740067ec50a8 + languageName: node + linkType: hard + +"d3-chord@npm:3": + version: 3.0.1 + resolution: "d3-chord@npm:3.0.1" + dependencies: + d3-path: "npm:1 - 3" + checksum: baa6013914af3f4fe1521f0d16de31a38eb8a71d08ff1dec4741f6f45a828661e5cd3935e39bd14e3032bdc78206c283ca37411da21d46ec3cfc520be6e7a7ce + languageName: node + linkType: hard + +"d3-color@npm:1 - 3, d3-color@npm:3": + version: 3.1.0 + resolution: "d3-color@npm:3.1.0" + checksum: a4e20e1115fa696fce041fbe13fbc80dc4c19150fa72027a7c128ade980bc0eeeba4bcf28c9e21f0bce0e0dbfe7ca5869ef67746541dcfda053e4802ad19783c + languageName: node + linkType: hard + +"d3-contour@npm:4": + version: 4.0.2 + resolution: "d3-contour@npm:4.0.2" + dependencies: + d3-array: "npm:^3.2.0" + checksum: 98bc5fbed6009e08707434a952076f39f1cd6ed8b9288253cc3e6a3286e4e80c63c62d84954b20e64bf6e4ededcc69add54d3db25e990784a59c04edd3449032 + languageName: node + linkType: hard + +"d3-delaunay@npm:6": + version: 6.0.4 + resolution: "d3-delaunay@npm:6.0.4" + dependencies: + delaunator: "npm:5" + checksum: 57c3aecd2525664b07c4c292aa11cf49b2752c0cf3f5257f752999399fe3c592de2d418644d79df1f255471eec8057a9cc0c3062ed7128cb3348c45f69597754 + languageName: node + linkType: hard + +"d3-dispatch@npm:1 - 3, d3-dispatch@npm:3": + version: 3.0.1 + resolution: "d3-dispatch@npm:3.0.1" + checksum: 6eca77008ce2dc33380e45d4410c67d150941df7ab45b91d116dbe6d0a3092c0f6ac184dd4602c796dc9e790222bad3ff7142025f5fd22694efe088d1d941753 + languageName: node + linkType: hard + +"d3-drag@npm:2 - 3, d3-drag@npm:3": + version: 3.0.0 + resolution: "d3-drag@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-selection: "npm:3" + checksum: d2556e8dc720741a443b595a30af403dd60642dfd938d44d6e9bfc4c71a962142f9a028c56b61f8b4790b65a34acad177d1263d66f103c3c527767b0926ef5aa + languageName: node + linkType: hard + +"d3-dsv@npm:1 - 3, d3-dsv@npm:3": + version: 3.0.1 + resolution: "d3-dsv@npm:3.0.1" + dependencies: + commander: "npm:7" + iconv-lite: "npm:0.6" + rw: "npm:1" + bin: + csv2json: bin/dsv2json.js + csv2tsv: bin/dsv2dsv.js + dsv2dsv: bin/dsv2dsv.js + dsv2json: bin/dsv2json.js + json2csv: bin/json2dsv.js + json2dsv: bin/json2dsv.js + json2tsv: bin/json2dsv.js + tsv2csv: bin/dsv2dsv.js + tsv2json: bin/dsv2json.js + checksum: 10e6af9e331950ed258f34ab49ac1b7060128ef81dcf32afc790bd1f7e8c3cc2aac7f5f875250a83f21f39bb5925fbd0872bb209f8aca32b3b77d32bab8a65ab + languageName: node + linkType: hard + +"d3-ease@npm:1 - 3, d3-ease@npm:3": + version: 3.0.1 + resolution: "d3-ease@npm:3.0.1" + checksum: fec8ef826c0cc35cda3092c6841e07672868b1839fcaf556e19266a3a37e6bc7977d8298c0fcb9885e7799bfdcef7db1baaba9cd4dcf4bc5e952cf78574a88b0 + languageName: node + linkType: hard + +"d3-fetch@npm:3": + version: 3.0.1 + resolution: "d3-fetch@npm:3.0.1" + dependencies: + d3-dsv: "npm:1 - 3" + checksum: 4f467a79bf290395ac0cbb5f7562483f6a18668adc4c8eb84c9d3eff048b6f6d3b6f55079ba1ebf1908dabe000c941d46be447f8d78453b2dad5fb59fb6aa93b + languageName: node + linkType: hard + +"d3-force@npm:3": + version: 3.0.0 + resolution: "d3-force@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-quadtree: "npm:1 - 3" + d3-timer: "npm:1 - 3" + checksum: 220a16a1a1ac62ba56df61028896e4b52be89c81040d20229c876efc8852191482c233f8a52bb5a4e0875c321b8e5cb6413ef3dfa4d8fe79eeb7d52c587f52cf + languageName: node + linkType: hard + +"d3-format@npm:1 - 3, d3-format@npm:3": + version: 3.1.0 + resolution: "d3-format@npm:3.1.0" + checksum: 049f5c0871ebce9859fc5e2f07f336b3c5bfff52a2540e0bac7e703fce567cd9346f4ad1079dd18d6f1e0eaa0599941c1810898926f10ac21a31fd0a34b4aa75 + languageName: node + linkType: hard + +"d3-geo@npm:3": + version: 3.1.0 + resolution: "d3-geo@npm:3.1.0" + dependencies: + d3-array: "npm:2.5.0 - 3" + checksum: 5b0a26d232787ca9e824a660827c28626a51004328dde7c76a1bd300d3cad8c7eeb55fea64c8cd6495d5a34fea434fb1418d59926a6cb24e6fb6e2b6f62c6bd9 + languageName: node + linkType: hard + +"d3-hierarchy@npm:3": + version: 3.1.2 + resolution: "d3-hierarchy@npm:3.1.2" + checksum: 6dcdb480539644aa7fc0d72dfc7b03f99dfbcdf02714044e8c708577e0d5981deb9d3e99bbbb2d26422b55bcc342ac89a0fa2ea6c9d7302e2fc0951dd96f89cf + languageName: node + linkType: hard + +"d3-interpolate@npm:1 - 3, d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:3": + version: 3.0.1 + resolution: "d3-interpolate@npm:3.0.1" + dependencies: + d3-color: "npm:1 - 3" + checksum: 19f4b4daa8d733906671afff7767c19488f51a43d251f8b7f484d5d3cfc36c663f0a66c38fe91eee30f40327443d799be17169f55a293a3ba949e84e57a33e6a + languageName: node + linkType: hard + +"d3-path@npm:1": + version: 1.0.9 + resolution: "d3-path@npm:1.0.9" + checksum: e35e84df5abc18091f585725b8235e1fa97efc287571585427d3a3597301e6c506dea56b11dfb3c06ca5858b3eb7f02c1bf4f6a716aa9eade01c41b92d497eb5 + languageName: node + linkType: hard + +"d3-path@npm:1 - 3, d3-path@npm:3, d3-path@npm:^3.1.0": + version: 3.1.0 + resolution: "d3-path@npm:3.1.0" + checksum: dc1d58ec87fa8319bd240cf7689995111a124b141428354e9637aa83059eb12e681f77187e0ada5dedfce346f7e3d1f903467ceb41b379bfd01cd8e31721f5da + languageName: node + linkType: hard + +"d3-polygon@npm:3": + version: 3.0.1 + resolution: "d3-polygon@npm:3.0.1" + checksum: e236aa7f33efa9a4072907af7dc119f85b150a0716759d4fe5f12f62573018264a6cbde8617fbfa6944a7ae48c1c0c8d3f39ae72e11f66dd471e9b5e668385df + languageName: node + linkType: hard + +"d3-quadtree@npm:1 - 3, d3-quadtree@npm:3": + version: 3.0.1 + resolution: "d3-quadtree@npm:3.0.1" + checksum: 18302d2548bfecaef788152397edec95a76400fd97d9d7f42a089ceb68d910f685c96579d74e3712d57477ed042b056881b47cd836a521de683c66f47ce89090 + languageName: node + linkType: hard + +"d3-random@npm:3": + version: 3.0.1 + resolution: "d3-random@npm:3.0.1" + checksum: 987a1a1bcbf26e6cf01fd89d5a265b463b2cea93560fc17d9b1c45e8ed6ff2db5924601bcceb808de24c94133f000039eb7fa1c469a7a844ccbf1170cbb25b41 + languageName: node + linkType: hard + +"d3-sankey@npm:^0.12.3": + version: 0.12.3 + resolution: "d3-sankey@npm:0.12.3" + dependencies: + d3-array: "npm:1 - 2" + d3-shape: "npm:^1.2.0" + checksum: 261debb01a13269f6fc53b9ebaef174a015d5ad646242c23995bf514498829ab8b8f920a7873724a7494288b46bea3ce7ebc5a920b745bc8ae4caa5885cf5204 + languageName: node + linkType: hard + +"d3-scale-chromatic@npm:3": + version: 3.0.0 + resolution: "d3-scale-chromatic@npm:3.0.0" + dependencies: + d3-color: "npm:1 - 3" + d3-interpolate: "npm:1 - 3" + checksum: 920a80f2e31b5686798c116e99d1671c32f55fb60fa920b742aa4ac5175b878c615adb4e55a246d65367e6e1061fdbcc55807be731fb5b18ae628d1df62bfac1 + languageName: node + linkType: hard + +"d3-scale@npm:4": + version: 4.0.2 + resolution: "d3-scale@npm:4.0.2" + dependencies: + d3-array: "npm:2.10.0 - 3" + d3-format: "npm:1 - 3" + d3-interpolate: "npm:1.2.0 - 3" + d3-time: "npm:2.1.1 - 3" + d3-time-format: "npm:2 - 4" + checksum: 65d9ad8c2641aec30ed5673a7410feb187a224d6ca8d1a520d68a7d6eac9d04caedbff4713d1e8545be33eb7fec5739983a7ab1d22d4e5ad35368c6729d362f1 + languageName: node + linkType: hard + +"d3-selection@npm:2 - 3, d3-selection@npm:3": + version: 3.0.0 + resolution: "d3-selection@npm:3.0.0" + checksum: e59096bbe8f0cb0daa1001d9bdd6dbc93a688019abc97d1d8b37f85cd3c286a6875b22adea0931b0c88410d025563e1643019161a883c516acf50c190a11b56b + languageName: node + linkType: hard + +"d3-shape@npm:3": + version: 3.2.0 + resolution: "d3-shape@npm:3.2.0" + dependencies: + d3-path: "npm:^3.1.0" + checksum: f1c9d1f09926daaf6f6193ae3b4c4b5521e81da7d8902d24b38694517c7f527ce3c9a77a9d3a5722ad1e3ff355860b014557b450023d66a944eabf8cfde37132 + languageName: node + linkType: hard + +"d3-shape@npm:^1.2.0": + version: 1.3.7 + resolution: "d3-shape@npm:1.3.7" + dependencies: + d3-path: "npm:1" + checksum: 548057ce59959815decb449f15632b08e2a1bdce208f9a37b5f98ec7629dda986c2356bc7582308405ce68aedae7d47b324df41507404df42afaf352907577ae + languageName: node + linkType: hard + +"d3-time-format@npm:2 - 4, d3-time-format@npm:4": + version: 4.1.0 + resolution: "d3-time-format@npm:4.1.0" + dependencies: + d3-time: "npm:1 - 3" + checksum: 735e00fb25a7fd5d418fac350018713ae394eefddb0d745fab12bbff0517f9cdb5f807c7bbe87bb6eeb06249662f8ea84fec075f7d0cd68609735b2ceb29d206 + languageName: node + linkType: hard + +"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:3": + version: 3.1.0 + resolution: "d3-time@npm:3.1.0" + dependencies: + d3-array: "npm:2 - 3" + checksum: a984f77e1aaeaa182679b46fbf57eceb6ebdb5f67d7578d6f68ef933f8eeb63737c0949991618a8d29472dbf43736c7d7f17c452b2770f8c1271191cba724ca1 + languageName: node + linkType: hard + +"d3-timer@npm:1 - 3, d3-timer@npm:3": + version: 3.0.1 + resolution: "d3-timer@npm:3.0.1" + checksum: d4c63cb4bb5461d7038aac561b097cd1c5673969b27cbdd0e87fa48d9300a538b9e6f39b4a7f0e3592ef4f963d858c8a9f0e92754db73116770856f2fc04561a + languageName: node + linkType: hard + +"d3-transition@npm:2 - 3, d3-transition@npm:3": + version: 3.0.1 + resolution: "d3-transition@npm:3.0.1" + dependencies: + d3-color: "npm:1 - 3" + d3-dispatch: "npm:1 - 3" + d3-ease: "npm:1 - 3" + d3-interpolate: "npm:1 - 3" + d3-timer: "npm:1 - 3" + peerDependencies: + d3-selection: 2 - 3 + checksum: 4e74535dda7024aa43e141635b7522bb70cf9d3dfefed975eb643b36b864762eca67f88fafc2ca798174f83ca7c8a65e892624f824b3f65b8145c6a1a88dbbad + languageName: node + linkType: hard + +"d3-zoom@npm:3": + version: 3.0.0 + resolution: "d3-zoom@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-drag: "npm:2 - 3" + d3-interpolate: "npm:1 - 3" + d3-selection: "npm:2 - 3" + d3-transition: "npm:2 - 3" + checksum: ee2036479049e70d8c783d594c444fe00e398246048e3f11a59755cd0e21de62ece3126181b0d7a31bf37bcf32fd726f83ae7dea4495ff86ec7736ce5ad36fd3 + languageName: node + linkType: hard + +"d3@npm:^7.4.0, d3@npm:^7.8.2": + version: 7.8.5 + resolution: "d3@npm:7.8.5" + dependencies: + d3-array: "npm:3" + d3-axis: "npm:3" + d3-brush: "npm:3" + d3-chord: "npm:3" + d3-color: "npm:3" + d3-contour: "npm:4" + d3-delaunay: "npm:6" + d3-dispatch: "npm:3" + d3-drag: "npm:3" + d3-dsv: "npm:3" + d3-ease: "npm:3" + d3-fetch: "npm:3" + d3-force: "npm:3" + d3-format: "npm:3" + d3-geo: "npm:3" + d3-hierarchy: "npm:3" + d3-interpolate: "npm:3" + d3-path: "npm:3" + d3-polygon: "npm:3" + d3-quadtree: "npm:3" + d3-random: "npm:3" + d3-scale: "npm:4" + d3-scale-chromatic: "npm:3" + d3-selection: "npm:3" + d3-shape: "npm:3" + d3-time: "npm:3" + d3-time-format: "npm:4" + d3-timer: "npm:3" + d3-transition: "npm:3" + d3-zoom: "npm:3" + checksum: 408758dcc2437cbff8cd207b9d82760030b5c53c1df6a2ce5b1a76633388a6892fd65c0632cfa83da963e239722d49805062e5fb05d99e0fb078bda14cb22222 + languageName: node + linkType: hard + +"dagre-d3-es@npm:7.0.10": + version: 7.0.10 + resolution: "dagre-d3-es@npm:7.0.10" + dependencies: + d3: "npm:^7.8.2" + lodash-es: "npm:^4.17.21" + checksum: 3e1bb6efe9a78cea3fe6ff265eb330692f057bf84c99d6a1d67db379231c37a1a1ca2e1ccc25a732ddf924cd5566062c033d88defd230debec324dc9256c6775 + languageName: node + linkType: hard + +"dayjs@npm:^1.11.7": + version: 1.11.10 + resolution: "dayjs@npm:1.11.10" + checksum: 4de9af50639d47df87f2e15fa36bb07e0f9ed1e9c52c6caa1482788ee9a384d668f1dbd00c54f82aaab163db07d61d2899384b8254da3a9184fc6deca080e2fe + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 + languageName: node + linkType: hard + +"decode-named-character-reference@npm:^1.0.0": + version: 1.0.2 + resolution: "decode-named-character-reference@npm:1.0.2" + dependencies: + character-entities: "npm:^2.0.0" + checksum: 66a9fc5d9b5385a2b3675c69ba0d8e893393d64057f7dbbb585265bb4fc05ec513d76943b8e5aac7d8016d20eea4499322cbf4cd6d54b466976b78f3a7587a4c + languageName: node + linkType: hard + +"delaunator@npm:5": + version: 5.0.0 + resolution: "delaunator@npm:5.0.0" + dependencies: + robust-predicates: "npm:^3.0.0" + checksum: 8655c1ad12dc58bd6350f882c12065ea415cfc809e4cac12b7b5c4941e981aaabee1afdcf13985dcd545d13d0143eb3805836f50e2b097af8137b204dfbea4f6 + languageName: node + linkType: hard + +"dequal@npm:^2.0.0": + version: 2.0.3 + resolution: "dequal@npm:2.0.3" + checksum: f98860cdf58b64991ae10205137c0e97d384c3a4edc7f807603887b7c4b850af1224a33d88012009f150861cbee4fa2d322c4cc04b9313bee312e47f6ecaa888 + languageName: node + linkType: hard + +"devlop@npm:^1.0.0, devlop@npm:^1.1.0": + version: 1.1.0 + resolution: "devlop@npm:1.1.0" + dependencies: + dequal: "npm:^2.0.0" + checksum: e0928ab8f94c59417a2b8389c45c55ce0a02d9ac7fd74ef62d01ba48060129e1d594501b77de01f3eeafc7cb00773819b0df74d96251cf20b31c5b3071f45c0e + languageName: node + linkType: hard + +"didyoumean@npm:^1.2.2": + version: 1.2.2 + resolution: "didyoumean@npm:1.2.2" + checksum: 95d0b53d23b851aacff56dfadb7ecfedce49da4232233baecfeecb7710248c4aa03f0aa8995062f0acafaf925adf8536bd7044a2e68316fd7d411477599bc27b + languageName: node + linkType: hard + +"diff@npm:^5.0.0": + version: 5.1.0 + resolution: "diff@npm:5.1.0" + checksum: 77a0d9beb9ed54796154ac2511872288432124ac90a1cabb1878783c9b4d81f1847f3b746a0630b1e836181461d2c76e1e6b95559bef86ed16294d114862e364 + languageName: node + linkType: hard + +"dlv@npm:^1.1.3": + version: 1.1.3 + resolution: "dlv@npm:1.1.3" + checksum: 03eb4e769f19a027fd5b43b59e8a05e3fd2100ac239ebb0bf9a745de35d449e2f25cfaf3aa3934664551d72856f4ae8b7822016ce5c42c2d27c18ae79429ec42 + languageName: node + linkType: hard + +"dompurify@npm:^3.0.5": + version: 3.0.8 + resolution: "dompurify@npm:3.0.8" + checksum: e89e03d3dbd99abd64cd90705ce2cdfbc60ee9726ee53f9860e8a2d91b828ef2c173e7031529f9a3aa169ad0fbb76115c6a6683b545bf1ac5d94cc6176fb2a50 + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.4.601": + version: 1.4.630 + resolution: "electron-to-chromium@npm:1.4.630" + checksum: dbe3b3437b00f978aa261e1ee9c80eebaba70dea601866b0d64e36f7146328c79bce8416652e4713cfeb0e22428cc7ec1751881860ec892fa32ec8de015d1a9e + languageName: node + linkType: hard + +"elkjs@npm:^0.9.0": + version: 0.9.1 + resolution: "elkjs@npm:0.9.1" + checksum: 2472dd26fafd009632f17609b36f8b61cfbd0c29d516d3e66ee54f2b078c21f559ff7db05de6590b1e0136272d141dfa8e7f7edbe963166ae45e4d5f9ed8c386 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: "npm:^0.6.2" + checksum: 36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 + languageName: node + linkType: hard + +"entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.1.1 + resolution: "escalade@npm:3.1.1" + checksum: afd02e6ca91ffa813e1108b5e7756566173d6bc0d1eb951cb44d6b21702ec17c1cf116cfe75d4a2b02e05acb0b808a7a9387d0d1ca5cf9c04ad03a8445c3e46d + languageName: node + linkType: hard + +"escape-string-regexp@npm:^1.0.5": + version: 1.0.5 + resolution: "escape-string-regexp@npm:1.0.5" + checksum: a968ad453dd0c2724e14a4f20e177aaf32bb384ab41b674a8454afe9a41c5e6fe8903323e0a1052f56289d04bd600f81278edf140b0fcc02f5cac98d0f5b5371 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^5.0.0": + version: 5.0.0 + resolution: "escape-string-regexp@npm:5.0.0" + checksum: 6366f474c6f37a802800a435232395e04e9885919873e382b157ab7e8f0feb8fed71497f84a6f6a81a49aab41815522f5839112bd38026d203aea0c91622df95 + languageName: node + linkType: hard + +"esprima@npm:^4.0.0": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 + languageName: node + linkType: hard + +"estree-util-attach-comments@npm:^2.0.0": + version: 2.1.1 + resolution: "estree-util-attach-comments@npm:2.1.1" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: cdb5fdb5809b376ca4a96afbcd916c3570b4bbf5d0115b8a9e1e8a10885d8d9fb549df0a16c077abb42ee35fa33192b69714bac25d4f3c43a36092288c9a64fd + languageName: node + linkType: hard + +"estree-util-build-jsx@npm:^2.0.0": + version: 2.2.2 + resolution: "estree-util-build-jsx@npm:2.2.2" + dependencies: + "@types/estree-jsx": "npm:^1.0.0" + estree-util-is-identifier-name: "npm:^2.0.0" + estree-walker: "npm:^3.0.0" + checksum: 2cef6ad6747f51934eba0601c3477ba08c98331cfe616635e08dfc89d06b9bbd370c4d80e87fe7d42d82776fa7840868201f48491b0ef9c808039f15fe4667e1 + languageName: node + linkType: hard + +"estree-util-is-identifier-name@npm:^2.0.0": + version: 2.1.0 + resolution: "estree-util-is-identifier-name@npm:2.1.0" + checksum: cc241a6998d30f4e8775ec34b042ef93e0085cd1bdf692a01f22e9b748f0866c76679475ff87935be1d8d5b1a7648be8cba366dc60866b372269f35feec756fe + languageName: node + linkType: hard + +"estree-util-to-js@npm:^1.1.0": + version: 1.2.0 + resolution: "estree-util-to-js@npm:1.2.0" + dependencies: + "@types/estree-jsx": "npm:^1.0.0" + astring: "npm:^1.8.0" + source-map: "npm:^0.7.0" + checksum: ad9c99dc34b0510ab813b485251acbf0abd06361c07b13c08da5d1611c279bee02ec09f2c269ae30b8d2da587115fc1fad4fa9f2f5ba69e094e758a3a4de7069 + languageName: node + linkType: hard + +"estree-util-value-to-estree@npm:^1.3.0": + version: 1.3.0 + resolution: "estree-util-value-to-estree@npm:1.3.0" + dependencies: + is-plain-obj: "npm:^3.0.0" + checksum: 8bf46c4629f55a6ad3a6c523277cd34591cf57dfcab01cf4f218a8780cd23d21901c393693484c449a46bad7b9cb6fbf24c3dd1c1b057e10fd6a076f24fd5f3f + languageName: node + linkType: hard + +"estree-util-visit@npm:^1.0.0": + version: 1.2.1 + resolution: "estree-util-visit@npm:1.2.1" + dependencies: + "@types/estree-jsx": "npm:^1.0.0" + "@types/unist": "npm:^2.0.0" + checksum: 3c47086ab25947a889fca9f58a842e0d27edadcad24dc393fdd7c9ad3419fe05b3c63b6fc9d6c9d8f50d32bca615cd0a3fe8d0e6b300fb94f74c91210b55ea5d + languageName: node + linkType: hard + +"estree-walker@npm:^3.0.0": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d + languageName: node + linkType: hard + +"execa@npm:^0.8.0": + version: 0.8.0 + resolution: "execa@npm:0.8.0" + dependencies: + cross-spawn: "npm:^5.0.1" + get-stream: "npm:^3.0.0" + is-stream: "npm:^1.1.0" + npm-run-path: "npm:^2.0.0" + p-finally: "npm:^1.0.0" + signal-exit: "npm:^3.0.0" + strip-eof: "npm:^1.0.0" + checksum: e6c085687024cd5d348cad98a12213f6ebad2e962c7f3298ea8608fd5ed2daad8d1e27e79bfe7104bf60d8d80b56dd60267a0667006c29019e4297c96ecfe99d + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 + languageName: node + linkType: hard + +"extend-shallow@npm:^2.0.1": + version: 2.0.1 + resolution: "extend-shallow@npm:2.0.1" + dependencies: + is-extendable: "npm:^0.1.0" + checksum: ee1cb0a18c9faddb42d791b2d64867bd6cfd0f3affb711782eb6e894dd193e2934a7f529426aac7c8ddb31ac5d38000a00aa2caf08aa3dfc3e1c8ff6ba340bd9 + languageName: node + linkType: hard + +"extend@npm:^3.0.0": + version: 3.0.2 + resolution: "extend@npm:3.0.2" + checksum: 73bf6e27406e80aa3e85b0d1c4fd987261e628064e170ca781125c0b635a3dabad5e05adbf07595ea0cf1e6c5396cacb214af933da7cbaf24fe75ff14818e8f9 + languageName: node + linkType: hard + +"fast-glob@npm:^3.3.0": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" + dependencies: + "@nodelib/fs.stat": "npm:^2.0.2" + "@nodelib/fs.walk": "npm:^1.2.3" + glob-parent: "npm:^5.1.2" + merge2: "npm:^1.3.0" + micromatch: "npm:^4.0.4" + checksum: 42baad7b9cd40b63e42039132bde27ca2cb3a4950d0a0f9abe4639ea1aa9d3e3b40f98b1fe31cbc0cc17b664c9ea7447d911a152fa34ec5b72977b125a6fc845 + languageName: node + linkType: hard + +"fastq@npm:^1.6.0": + version: 1.16.0 + resolution: "fastq@npm:1.16.0" + dependencies: + reusify: "npm:^1.0.4" + checksum: 38c1b49adba639af020727284a02af021acab764efd7f088bc31364e8a5b01ce9031eb6c5f7f304019b8267c3b7c236e79d6904884f50f94f83b1700b8a6619a + languageName: node + linkType: hard + +"fill-range@npm:^7.0.1": + version: 7.0.1 + resolution: "fill-range@npm:7.0.1" + dependencies: + to-regex-range: "npm:^5.0.1" + checksum: 7cdad7d426ffbaadf45aeb5d15ec675bbd77f7597ad5399e3d2766987ed20bda24d5fac64b3ee79d93276f5865608bb22344a26b9b1ae6c4d00bd94bf611623f + languageName: node + linkType: hard + +"flexsearch@npm:^0.7.31": + version: 0.7.43 + resolution: "flexsearch@npm:0.7.43" + checksum: 797dc474ed97750b8e85c118b1af63eb2709da5fc05defcb13e96515774f28743ccb2448b63f3b703cf1ca571928c006069503dacf7d177bc07b9ee15e1f85d0 + languageName: node + linkType: hard + +"focus-visible@npm:^5.2.0": + version: 5.2.0 + resolution: "focus-visible@npm:5.2.0" + checksum: bc746775e4c17d05faf7219a91fd5ae6fec320b87f20cde5402eff17fab148b6253f25748f0235b3110528a1335ee0c6d4dc3692cc6b6174d0ebd253dd28a50d + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.1.1 + resolution: "foreground-child@npm:3.1.1" + dependencies: + cross-spawn: "npm:^7.0.0" + signal-exit: "npm:^4.0.1" + checksum: 9700a0285628abaeb37007c9a4d92bd49f67210f09067638774338e146c8e9c825c5c877f072b2f75f41dc6a2d0be8664f79ffc03f6576649f54a84fb9b47de0 + languageName: node + linkType: hard + +"fraction.js@npm:^4.3.6": + version: 4.3.7 + resolution: "fraction.js@npm:4.3.7" + checksum: df291391beea9ab4c263487ffd9d17fed162dbb736982dee1379b2a8cc94e4e24e46ed508c6d278aded9080ba51872f1bc5f3a5fd8d7c74e5f105b508ac28711 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: "npm:^3.0.0" + checksum: 703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"get-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "get-stream@npm:3.0.0" + checksum: 003f5f3b8870da59c6aafdf6ed7e7b07b48c2f8629cd461bd3900726548b6b8cfa2e14d6b7814fbb08f07a42f4f738407fa70b989928b2783a76b278505bba22 + languageName: node + linkType: hard + +"git-up@npm:^7.0.0": + version: 7.0.0 + resolution: "git-up@npm:7.0.0" + dependencies: + is-ssh: "npm:^1.4.0" + parse-url: "npm:^8.1.0" + checksum: a3fa02e1a63c7c824b5ebbf23f4a9a6b34dd80031114c5dd8adb7ef53493642e39d3d80dfef4025a452128400c35c2c138d20a0f6ae5d7d7ef70d9ba13083d34 + languageName: node + linkType: hard + +"git-url-parse@npm:^13.1.0": + version: 13.1.1 + resolution: "git-url-parse@npm:13.1.1" + dependencies: + git-up: "npm:^7.0.0" + checksum: 9304e6fbc1a6acf5e351e84ad87574fa6b840ccbe531afbbce9ba38e01fcacf6adf386ef7593daa037da59d9fd43b5d7c5232d5648638f8301cc2f18d00ad386 + languageName: node + linkType: hard + +"github-slugger@npm:^2.0.0": + version: 2.0.0 + resolution: "github-slugger@npm:2.0.0" + checksum: 21b912b6b1e48f1e5a50b2292b48df0ff6abeeb0691b161b3d93d84f4ae6b1acd6ae23702e914af7ea5d441c096453cf0f621b72d57893946618d21dd1a1c486 + languageName: node + linkType: hard + +"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: "npm:^4.0.1" + checksum: cab87638e2112bee3f839ef5f6e0765057163d39c66be8ec1602f3823da4692297ad4e972de876ea17c44d652978638d2fd583c6713d0eb6591706825020c9ee + languageName: node + linkType: hard + +"glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: "npm:^4.0.3" + checksum: 317034d88654730230b3f43bb7ad4f7c90257a426e872ea0bf157473ac61c99bf5d205fad8f0185f989be8d2fa6d3c7dce1645d99d545b6ea9089c39f838e7f8 + languageName: node + linkType: hard + +"glob-to-regexp@npm:^0.4.1": + version: 0.4.1 + resolution: "glob-to-regexp@npm:0.4.1" + checksum: 0486925072d7a916f052842772b61c3e86247f0a80cc0deb9b5a3e8a1a9faad5b04fb6f58986a09f34d3e96cd2a22a24b7e9882fb1cf904c31e9a310de96c429 + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.3.5" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry: "npm:^1.10.1" + bin: + glob: dist/esm/bin.mjs + checksum: 13d8a1feb7eac7945f8c8480e11cd4a44b24d26503d99a8d8ac8d5aefbf3e9802a2b6087318a829fad04cb4e829f25c5f4f1110c68966c498720dd261c7e344d + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"gray-matter@npm:^4.0.3": + version: 4.0.3 + resolution: "gray-matter@npm:4.0.3" + dependencies: + js-yaml: "npm:^3.13.1" + kind-of: "npm:^6.0.2" + section-matter: "npm:^1.0.0" + strip-bom-string: "npm:^1.0.0" + checksum: e38489906dad4f162ca01e0dcbdbed96d1a53740cef446b9bf76d80bec66fa799af07776a18077aee642346c5e1365ed95e4c91854a12bf40ba0d4fb43a625a6 + languageName: node + linkType: hard + +"has-flag@npm:^2.0.0": + version: 2.0.0 + resolution: "has-flag@npm:2.0.0" + checksum: 5e1f136c7f801c2719048bedfabcf834a1ed46276cd4c98c6fcddb89a482f5d6a16df0771a38805cfc2d9010b4de157909e1a71b708e1d339b6e311041bde9b4 + languageName: node + linkType: hard + +"hash-obj@npm:^4.0.0": + version: 4.0.0 + resolution: "hash-obj@npm:4.0.0" + dependencies: + is-obj: "npm:^3.0.0" + sort-keys: "npm:^5.0.0" + type-fest: "npm:^1.0.2" + checksum: af0a8bd3905afa2b9bd05ec75e37d904c66f6621ae185d53699fc7e5baf8157aeff6f4b9ae3c579da08aae6a5b2536c445c4dd1eecb94070c8717b63eeca97de + languageName: node + linkType: hard + +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 5d415b114f410661208c95e7ab4879f1cc2765b8daceff4dc8718317d1cb7b9ffa7c5d1eafd9a4389c9aab7445d6ea88e05f3096cb1e529618b55304956b87fc + languageName: node + linkType: hard + +"hast-util-from-dom@npm:^5.0.0": + version: 5.0.0 + resolution: "hast-util-from-dom@npm:5.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + hastscript: "npm:^8.0.0" + web-namespaces: "npm:^2.0.0" + checksum: 1b0a9d65eb8f8cd3616559190bb6db271b7b4f72a13c5dc16abac264b6f7145beb408fbaa497d1b5c725d55392b951972d8313802bfe90ccac33f888ec34c63c + languageName: node + linkType: hard + +"hast-util-from-html-isomorphic@npm:^2.0.0": + version: 2.0.0 + resolution: "hast-util-from-html-isomorphic@npm:2.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + hast-util-from-dom: "npm:^5.0.0" + hast-util-from-html: "npm:^2.0.0" + unist-util-remove-position: "npm:^5.0.0" + checksum: fc68d9245e794483a802d5c85a9f6c25959e00db78cc796411efc965134f3206f9cc9fa38134572ea781ad74663e801f1f83202007b208e27a770855566a62b6 + languageName: node + linkType: hard + +"hast-util-from-html@npm:^2.0.0": + version: 2.0.1 + resolution: "hast-util-from-html@npm:2.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + devlop: "npm:^1.1.0" + hast-util-from-parse5: "npm:^8.0.0" + parse5: "npm:^7.0.0" + vfile: "npm:^6.0.0" + vfile-message: "npm:^4.0.0" + checksum: 856ceec209940ac4f9db52bf6338b97fb11f27e6d5b930f89676bc16ee282c06f9ff2a17254280803aefdf740507cf3004f181d0286b04dda11907852decbe77 + languageName: node + linkType: hard + +"hast-util-from-parse5@npm:^8.0.0": + version: 8.0.1 + resolution: "hast-util-from-parse5@npm:8.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/unist": "npm:^3.0.0" + devlop: "npm:^1.0.0" + hastscript: "npm:^8.0.0" + property-information: "npm:^6.0.0" + vfile: "npm:^6.0.0" + vfile-location: "npm:^5.0.0" + web-namespaces: "npm:^2.0.0" + checksum: 4a30bb885cff1f0e023c429ae3ece73fe4b03386f07234bf23f5555ca087c2573ff4e551035b417ed7615bde559f394cdaf1db2b91c3b7f0575f3563cd238969 + languageName: node + linkType: hard + +"hast-util-is-element@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-is-element@npm:3.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + checksum: f5361e4c9859c587ca8eb0d8343492f3077ccaa0f58a44cd09f35d5038f94d65152288dcd0c19336ef2c9491ec4d4e45fde2176b05293437021570aa0bc3613b + languageName: node + linkType: hard + +"hast-util-parse-selector@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-parse-selector@npm:4.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + checksum: 5e98168cb44470dc274aabf1a28317e4feb09b1eaf7a48bbaa8c1de1b43a89cd195cb1284e535698e658e3ec26ad91bc5e52c9563c36feb75abbc68aaf68fb9f + languageName: node + linkType: hard + +"hast-util-raw@npm:^9.0.0": + version: 9.0.1 + resolution: "hast-util-raw@npm:9.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/unist": "npm:^3.0.0" + "@ungap/structured-clone": "npm:^1.0.0" + hast-util-from-parse5: "npm:^8.0.0" + hast-util-to-parse5: "npm:^8.0.0" + html-void-elements: "npm:^3.0.0" + mdast-util-to-hast: "npm:^13.0.0" + parse5: "npm:^7.0.0" + unist-util-position: "npm:^5.0.0" + unist-util-visit: "npm:^5.0.0" + vfile: "npm:^6.0.0" + web-namespaces: "npm:^2.0.0" + zwitch: "npm:^2.0.0" + checksum: 60ee6495681f020930380649af58b2a6ca081bec1abd1089f58b0ee892eac2c87dc2077fb30370e51848734b58d2d539e3cde5148c18aa70a89f2c7285e57c91 + languageName: node + linkType: hard + +"hast-util-to-estree@npm:^2.0.0": + version: 2.3.3 + resolution: "hast-util-to-estree@npm:2.3.3" + dependencies: + "@types/estree": "npm:^1.0.0" + "@types/estree-jsx": "npm:^1.0.0" + "@types/hast": "npm:^2.0.0" + "@types/unist": "npm:^2.0.0" + comma-separated-tokens: "npm:^2.0.0" + estree-util-attach-comments: "npm:^2.0.0" + estree-util-is-identifier-name: "npm:^2.0.0" + hast-util-whitespace: "npm:^2.0.0" + mdast-util-mdx-expression: "npm:^1.0.0" + mdast-util-mdxjs-esm: "npm:^1.0.0" + property-information: "npm:^6.0.0" + space-separated-tokens: "npm:^2.0.0" + style-to-object: "npm:^0.4.1" + unist-util-position: "npm:^4.0.0" + zwitch: "npm:^2.0.0" + checksum: 5947b5030a6d20c193f5ea576cc751507e0b30d00f91e40a5208ca3a7add03a3862795a83600c0fdadf19c8b051917c7904715fa7dd358f04603d67a36341c38 + languageName: node + linkType: hard + +"hast-util-to-parse5@npm:^8.0.0": + version: 8.0.0 + resolution: "hast-util-to-parse5@npm:8.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + comma-separated-tokens: "npm:^2.0.0" + devlop: "npm:^1.0.0" + property-information: "npm:^6.0.0" + space-separated-tokens: "npm:^2.0.0" + web-namespaces: "npm:^2.0.0" + zwitch: "npm:^2.0.0" + checksum: 3c0c7fba026e0c4be4675daf7277f9ff22ae6da801435f1b7104f7740de5422576f1c025023c7b3df1d0a161e13a04c6ab8f98ada96eb50adb287b537849a2bd + languageName: node + linkType: hard + +"hast-util-to-text@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-to-text@npm:4.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/unist": "npm:^3.0.0" + hast-util-is-element: "npm:^3.0.0" + unist-util-find-after: "npm:^5.0.0" + checksum: 868f6b871b12db496e49f07470b87415ef77a3b439d4fce007a1e42c438f8320d76c5231b37e54f4188bce2af1e24c76728d86ee4cf076245ec86d3b6820dbe2 + languageName: node + linkType: hard + +"hast-util-whitespace@npm:^2.0.0": + version: 2.0.1 + resolution: "hast-util-whitespace@npm:2.0.1" + checksum: dcf6ebab091c802ffa7bb3112305c7631c15adb6c07a258f5528aefbddf82b4e162c8310ef426c48dc1dc623982cc33920e6dde5a50015d307f2778dcf6c2487 + languageName: node + linkType: hard + +"hastscript@npm:^8.0.0": + version: 8.0.0 + resolution: "hastscript@npm:8.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + comma-separated-tokens: "npm:^2.0.0" + hast-util-parse-selector: "npm:^4.0.0" + property-information: "npm:^6.0.0" + space-separated-tokens: "npm:^2.0.0" + checksum: f0b54bbdd710854b71c0f044612db0fe1b5e4d74fa2001633dc8c535c26033269f04f536f9fd5b03f234de1111808f9e230e9d19493bf919432bb24d541719e0 + languageName: node + linkType: hard + +"heap@npm:^0.2.6": + version: 0.2.7 + resolution: "heap@npm:0.2.7" + checksum: 341c5d51ae13dc8346c371a8a69c57c972fcb9a3233090d3dd5ba29d483d6b5b4e75492443cbfeacd46608bb30e6680f646ffb7a6205900221735587d07a79b6 + languageName: node + linkType: hard + +"html-void-elements@npm:^3.0.0": + version: 3.0.0 + resolution: "html-void-elements@npm:3.0.0" + checksum: a8b9ec5db23b7c8053876dad73a0336183e6162bf6d2677376d8b38d654fdc59ba74fdd12f8812688f7db6fad451210c91b300e472afc0909224e0a44c8610d2 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "http-proxy-agent@npm:7.0.0" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: a11574ff39436cee3c7bc67f259444097b09474605846ddd8edf0bf4ad8644be8533db1aa463426e376865047d05dc22755e638632819317c0c2f1b2196657c8 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.2 + resolution: "https-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:4" + checksum: 7735eb90073db087e7e79312e3d97c8c04baf7ea7ca7b013382b6a45abbaa61b281041a98f4e13c8c80d88f843785bcc84ba189165b4b4087b1e3496ba656d77 + languageName: node + linkType: hard + +"iconv-lite@npm:0.6, iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f + languageName: node + linkType: hard + +"inline-style-parser@npm:0.1.1": + version: 0.1.1 + resolution: "inline-style-parser@npm:0.1.1" + checksum: 08832a533f51a1e17619f2eabf2f5ec5e956d6dcba1896351285c65df022c9420de61d73256e1dca8015a52abf96cc84ddc3b73b898b22de6589d3962b5e501b + languageName: node + linkType: hard + +"internmap@npm:1 - 2": + version: 2.0.3 + resolution: "internmap@npm:2.0.3" + checksum: 8cedd57f07bbc22501516fbfc70447f0c6812871d471096fad9ea603516eacc2137b633633daf432c029712df0baefd793686388ddf5737e3ea15074b877f7ed + languageName: node + linkType: hard + +"internmap@npm:^1.0.0": + version: 1.0.1 + resolution: "internmap@npm:1.0.1" + checksum: 60942be815ca19da643b6d4f23bd0bf4e8c97abbd080fb963fe67583b60bdfb3530448ad4486bae40810e92317bded9995cc31411218acc750d72cd4e8646eee + languageName: node + linkType: hard + +"intersection-observer@npm:^0.12.2": + version: 0.12.2 + resolution: "intersection-observer@npm:0.12.2" + checksum: 9591f46b2b742f5801ed69dbc8860f487771b4af8361e7a5dcb28a377beff2ba56336a2b090af261825430d225dae9417121496d2e6925e000e4a469958843ff + languageName: node + linkType: hard + +"ip@npm:^2.0.0": + version: 2.0.0 + resolution: "ip@npm:2.0.0" + checksum: 8d186cc5585f57372847ae29b6eba258c68862055e18a75cc4933327232cb5c107f89800ce29715d542eef2c254fbb68b382e780a7414f9ee7caf60b7a473958 + languageName: node + linkType: hard + +"is-alphabetical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphabetical@npm:2.0.1" + checksum: 932367456f17237533fd1fc9fe179df77957271020b83ea31da50e5cc472d35ef6b5fb8147453274ffd251134472ce24eb6f8d8398d96dee98237cdb81a6c9a7 + languageName: node + linkType: hard + +"is-alphanumerical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphanumerical@npm:2.0.1" + dependencies: + is-alphabetical: "npm:^2.0.0" + is-decimal: "npm:^2.0.0" + checksum: 4b35c42b18e40d41378293f82a3ecd9de77049b476f748db5697c297f686e1e05b072a6aaae2d16f54d2a57f85b00cbbe755c75f6d583d1c77d6657bd0feb5a2 + languageName: node + linkType: hard + +"is-binary-path@npm:~2.1.0": + version: 2.1.0 + resolution: "is-binary-path@npm:2.1.0" + dependencies: + binary-extensions: "npm:^2.0.0" + checksum: a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38 + languageName: node + linkType: hard + +"is-buffer@npm:^2.0.0": + version: 2.0.5 + resolution: "is-buffer@npm:2.0.5" + checksum: e603f6fced83cf94c53399cff3bda1a9f08e391b872b64a73793b0928be3e5f047f2bcece230edb7632eaea2acdbfcb56c23b33d8a20c820023b230f1485679a + languageName: node + linkType: hard + +"is-core-module@npm:^2.13.0": + version: 2.13.1 + resolution: "is-core-module@npm:2.13.1" + dependencies: + hasown: "npm:^2.0.0" + checksum: 2cba9903aaa52718f11c4896dabc189bab980870aae86a62dc0d5cedb546896770ee946fb14c84b7adf0735f5eaea4277243f1b95f5cefa90054f92fbcac2518 + languageName: node + linkType: hard + +"is-decimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-decimal@npm:2.0.1" + checksum: 8085dd66f7d82f9de818fba48b9e9c0429cb4291824e6c5f2622e96b9680b54a07a624cfc663b24148b8e853c62a1c987cfe8b0b5a13f5156991afaf6736e334 + languageName: node + linkType: hard + +"is-extendable@npm:^0.1.0": + version: 0.1.1 + resolution: "is-extendable@npm:0.1.1" + checksum: dd5ca3994a28e1740d1e25192e66eed128e0b2ff161a7ea348e87ae4f616554b486854de423877a2a2c171d5f7cd6e8093b91f54533bc88a59ee1c9838c43879 + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: 5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc + languageName: node + linkType: hard + +"is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: "npm:^2.1.1" + checksum: 17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a + languageName: node + linkType: hard + +"is-hexadecimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-hexadecimal@npm:2.0.1" + checksum: 3eb60fe2f1e2bbc760b927dcad4d51eaa0c60138cf7fc671803f66353ad90c301605b502c7ea4c6bb0548e1c7e79dfd37b73b632652e3b76030bba603a7e9626 + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 + languageName: node + linkType: hard + +"is-obj@npm:^3.0.0": + version: 3.0.0 + resolution: "is-obj@npm:3.0.0" + checksum: 48d678fa15c56fd38353634ae2106a538827af9050211b18df13540dba0b38aa25c5cb498648a01311bf493a99ac3ce416576649b8cace10bcce7344611fa56a + languageName: node + linkType: hard + +"is-plain-obj@npm:^3.0.0": + version: 3.0.0 + resolution: "is-plain-obj@npm:3.0.0" + checksum: 8e6483bfb051d42ec9c704c0ede051a821c6b6f9a6c7a3e3b55aa855e00981b0580c8f3b1f5e2e62649b39179b1abfee35d6f8086d999bfaa32c1908d29b07bc + languageName: node + linkType: hard + +"is-plain-obj@npm:^4.0.0": + version: 4.1.0 + resolution: "is-plain-obj@npm:4.1.0" + checksum: 32130d651d71d9564dc88ba7e6fda0e91a1010a3694648e9f4f47bb6080438140696d3e3e15c741411d712e47ac9edc1a8a9de1fe76f3487b0d90be06ac9975e + languageName: node + linkType: hard + +"is-reference@npm:^3.0.0": + version: 3.0.2 + resolution: "is-reference@npm:3.0.2" + dependencies: + "@types/estree": "npm:*" + checksum: 652d31b405e8e8269071cee78fe874b072745012eba202c6dc86880fd603a65ae043e3160990ab4a0a4b33567cbf662eecf3bc6b3c2c1550e6c2b6cf885ce5aa + languageName: node + linkType: hard + +"is-ssh@npm:^1.4.0": + version: 1.4.0 + resolution: "is-ssh@npm:1.4.0" + dependencies: + protocols: "npm:^2.0.1" + checksum: 3eb30d1bcb4507cd25562e7ac61a1c0aa31772134c67cec9c3afe6f4d57ec17e8c2892600a608e8e583f32f53f36465b8968c0305f2855cfbff95acfd049e113 + languageName: node + linkType: hard + +"is-stream@npm:^1.1.0": + version: 1.1.0 + resolution: "is-stream@npm:1.1.0" + checksum: b8ae7971e78d2e8488d15f804229c6eed7ed36a28f8807a1815938771f4adff0e705218b7dab968270433f67103e4fef98062a0beea55d64835f705ee72c7002 + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 + languageName: node + linkType: hard + +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: f01d8f972d894cd7638bc338e9ef5ddb86f7b208ce177a36d718eac96ec86638a6efa17d0221b10073e64b45edc2ce15340db9380b1f5d5c5d000cbc517dc111 + languageName: node + linkType: hard + +"jiti@npm:^1.19.1": + version: 1.21.0 + resolution: "jiti@npm:1.21.0" + bin: + jiti: bin/jiti.js + checksum: 7f361219fe6c7a5e440d5f1dba4ab763a5538d2df8708cdc22561cf25ea3e44b837687931fca7cdd8cdd9f567300e90be989dd1321650045012d8f9ed6aab07f + languageName: node + linkType: hard + +"js-tokens@npm:^3.0.0 || ^4.0.0": + version: 4.0.0 + resolution: "js-tokens@npm:4.0.0" + checksum: e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed + languageName: node + linkType: hard + +"js-yaml@npm:^3.13.1": + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" + dependencies: + argparse: "npm:^1.0.7" + esprima: "npm:^4.0.0" + bin: + js-yaml: bin/js-yaml.js + checksum: 6746baaaeac312c4db8e75fa22331d9a04cccb7792d126ed8ce6a0bbcfef0cedaddd0c5098fade53db067c09fe00aa1c957674b4765610a8b06a5a189e46433b + languageName: node + linkType: hard + +"js-yaml@npm:^4.0.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: "npm:^2.0.1" + bin: + js-yaml: bin/js-yaml.js + checksum: 184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f + languageName: node + linkType: hard + +"jsonc-parser@npm:^3.2.0": + version: 3.2.0 + resolution: "jsonc-parser@npm:3.2.0" + checksum: 5a12d4d04dad381852476872a29dcee03a57439574e4181d91dca71904fcdcc5e8e4706c0a68a2c61ad9810e1e1c5806b5100d52d3e727b78f5cdc595401045b + languageName: node + linkType: hard + +"katex@npm:^0.16.0, katex@npm:^0.16.9": + version: 0.16.9 + resolution: "katex@npm:0.16.9" + dependencies: + commander: "npm:^8.3.0" + bin: + katex: cli.js + checksum: 750b1d61063eda970b97bfb2e8e26c898548ce2b544286813982498b1ce1d4cfae41dd32fa7e9488b6118a4c8df5cf06871746993d45227de34ea224c63199df + languageName: node + linkType: hard + +"khroma@npm:^2.0.0": + version: 2.1.0 + resolution: "khroma@npm:2.1.0" + checksum: 634d98753ff5d2540491cafeb708fc98de0d43f4e6795256d5c8f6e3ad77de93049ea41433928fda3697adf7bbe6fe27351858f6d23b78f8b5775ef314c59891 + languageName: node + linkType: hard + +"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2": + version: 6.0.3 + resolution: "kind-of@npm:6.0.3" + checksum: 61cdff9623dabf3568b6445e93e31376bee1cdb93f8ba7033d86022c2a9b1791a1d9510e026e6465ebd701a6dd2f7b0808483ad8838341ac52f003f512e0b4c4 + languageName: node + linkType: hard + +"kleur@npm:^4.0.3": + version: 4.1.5 + resolution: "kleur@npm:4.1.5" + checksum: e9de6cb49657b6fa70ba2d1448fd3d691a5c4370d8f7bbf1c2f64c24d461270f2117e1b0afe8cb3114f13bbd8e51de158c2a224953960331904e636a5e4c0f2a + languageName: node + linkType: hard + +"layout-base@npm:^1.0.0": + version: 1.0.2 + resolution: "layout-base@npm:1.0.2" + checksum: 2a55d0460fd9f6ed53d7e301b9eb3dea19bda03815d616a40665ce6dc75c1f4d62e1ca19a897da1cfaf6de1b91de59cd6f2f79ba1258f3d7fccc7d46ca7f3337 + languageName: node + linkType: hard + +"layout-base@npm:^2.0.0": + version: 2.0.1 + resolution: "layout-base@npm:2.0.1" + checksum: a44df9ef3cbff9916a10f616635e22b5787c89fa62b2fec6f99e8e6ee512c7cebd22668ce32dab5a83c934ba0a309c51a678aa0b40d70853de6c357893c0a88b + languageName: node + linkType: hard + +"lilconfig@npm:^2.1.0": + version: 2.1.0 + resolution: "lilconfig@npm:2.1.0" + checksum: 64645641aa8d274c99338e130554abd6a0190533c0d9eb2ce7ebfaf2e05c7d9961f3ffe2bfa39efd3b60c521ba3dd24fa236fe2775fc38501bf82bf49d4678b8 + languageName: node + linkType: hard + +"lilconfig@npm:^3.0.0": + version: 3.0.0 + resolution: "lilconfig@npm:3.0.0" + checksum: 7f5ee7a658dc016cacf146815e8d88b06f06f4402823b8b0934e305a57a197f55ccc9c5cd4fb5ea1b2b821c8ccaf2d54abd59602a4931af06eabda332388d3e6 + languageName: node + linkType: hard + +"lines-and-columns@npm:^1.1.6": + version: 1.2.4 + resolution: "lines-and-columns@npm:1.2.4" + checksum: 3da6ee62d4cd9f03f5dc90b4df2540fb85b352081bee77fe4bbcd12c9000ead7f35e0a38b8d09a9bb99b13223446dd8689ff3c4959807620726d788701a83d2d + languageName: node + linkType: hard + +"lodash-es@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash-es@npm:4.17.21" + checksum: fb407355f7e6cd523a9383e76e6b455321f0f153a6c9625e21a8827d10c54c2a2341bd2ae8d034358b60e07325e1330c14c224ff582d04612a46a4f0479ff2f2 + languageName: node + linkType: hard + +"lodash.get@npm:^4.4.2": + version: 4.4.2 + resolution: "lodash.get@npm:4.4.2" + checksum: 48f40d471a1654397ed41685495acb31498d5ed696185ac8973daef424a749ca0c7871bf7b665d5c14f5cc479394479e0307e781f61d5573831769593411be6e + languageName: node + linkType: hard + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c + languageName: node + linkType: hard + +"longest-streak@npm:^3.0.0": + version: 3.1.0 + resolution: "longest-streak@npm:3.1.0" + checksum: 7c2f02d0454b52834d1bcedef79c557bd295ee71fdabb02d041ff3aa9da48a90b5df7c0409156dedbc4df9b65da18742652aaea4759d6ece01f08971af6a7eaa + languageName: node + linkType: hard + +"loose-envify@npm:^1.1.0": + version: 1.4.0 + resolution: "loose-envify@npm:1.4.0" + dependencies: + js-tokens: "npm:^3.0.0 || ^4.0.0" + bin: + loose-envify: cli.js + checksum: 655d110220983c1a4b9c0c679a2e8016d4b67f6e9c7b5435ff5979ecdb20d0813f4dec0a08674fcbdd4846a3f07edbb50a36811fd37930b94aaa0d9daceb017e + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.1.0 + resolution: "lru-cache@npm:10.1.0" + checksum: 778bc8b2626daccd75f24c4b4d10632496e21ba064b126f526c626fbdbc5b28c472013fccd45d7646b9e1ef052444824854aed617b59cd570d01a8b7d651fc1e + languageName: node + linkType: hard + +"lru-cache@npm:^4.0.1": + version: 4.1.5 + resolution: "lru-cache@npm:4.1.5" + dependencies: + pseudomap: "npm:^1.0.2" + yallist: "npm:^2.1.2" + checksum: 1ca5306814e5add9ec63556d6fd9b24a4ecdeaef8e9cea52cbf30301e6b88c8d8ddc7cab45b59b56eb763e6c45af911585dc89925a074ab65e1502e3fe8103cf + languageName: node + linkType: hard + +"lru-cache@npm:^6.0.0": + version: 6.0.0 + resolution: "lru-cache@npm:6.0.0" + dependencies: + yallist: "npm:^4.0.0" + checksum: cb53e582785c48187d7a188d3379c181b5ca2a9c78d2bce3e7dee36f32761d1c42983da3fe12b55cb74e1779fa94cdc2e5367c028a9b35317184ede0c07a30a9 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" + dependencies: + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" + http-cache-semantics: "npm:^4.1.1" + is-lambda: "npm:^1.0.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^3.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^0.6.3" + promise-retry: "npm:^2.0.1" + ssri: "npm:^10.0.0" + checksum: 43b9f6dcbc6fe8b8604cb6396957c3698857a15ba4dbc38284f7f0e61f248300585ef1eb8cc62df54e9c724af977e45b5cdfd88320ef7f53e45070ed3488da55 + languageName: node + linkType: hard + +"markdown-extensions@npm:^1.0.0": + version: 1.1.1 + resolution: "markdown-extensions@npm:1.1.1" + checksum: eb9154016502ad1fb4477683ddb5cae8ba3ca06451b381b04dc4c34e91d8d168129d50d404b717d6bf7d458e13088c109303fc72d57cee7151a6082b0e7bba71 + languageName: node + linkType: hard + +"markdown-table@npm:^3.0.0": + version: 3.0.3 + resolution: "markdown-table@npm:3.0.3" + checksum: 47433a3f31e4637a184e38e873ab1d2fadfb0106a683d466fec329e99a2d8dfa09f091fa42202c6f13ec94aef0199f449a684b28042c636f2edbc1b7e1811dcd + languageName: node + linkType: hard + +"match-sorter@npm:^6.3.1": + version: 6.3.1 + resolution: "match-sorter@npm:6.3.1" + dependencies: + "@babel/runtime": "npm:^7.12.5" + remove-accents: "npm:0.4.2" + checksum: fb805e1f8cd1a41846dd5dcbba810a3bff3e1436a34a8226201d3f7518970171a7dbedb0d99677a6dce2a2925e4fc3cf1d0d82a1203ac9ef65d13d5d290b1dad + languageName: node + linkType: hard + +"mdast-util-definitions@npm:^5.0.0": + version: 5.1.2 + resolution: "mdast-util-definitions@npm:5.1.2" + dependencies: + "@types/mdast": "npm:^3.0.0" + "@types/unist": "npm:^2.0.0" + unist-util-visit: "npm:^4.0.0" + checksum: da9049c15562e44ee4ea4a36113d98c6c9eaa3d8a17d6da2aef6a0626376dcd01d9ec007d77a8dfcad6d0cbd5c32a4abbad72a3f48c3172a55934c7d9a916480 + languageName: node + linkType: hard + +"mdast-util-find-and-replace@npm:^2.0.0": + version: 2.2.2 + resolution: "mdast-util-find-and-replace@npm:2.2.2" + dependencies: + "@types/mdast": "npm:^3.0.0" + escape-string-regexp: "npm:^5.0.0" + unist-util-is: "npm:^5.0.0" + unist-util-visit-parents: "npm:^5.0.0" + checksum: ce935f4bd4aeab47f91531a7f09dfab89aaeea62ad31029b43185c5b626921357703d8e5093c13073c097fdabfc57cb2f884d7dfad83dbe7239e351375d6797c + languageName: node + linkType: hard + +"mdast-util-from-markdown@npm:^1.0.0, mdast-util-from-markdown@npm:^1.1.0, mdast-util-from-markdown@npm:^1.3.0": + version: 1.3.1 + resolution: "mdast-util-from-markdown@npm:1.3.1" + dependencies: + "@types/mdast": "npm:^3.0.0" + "@types/unist": "npm:^2.0.0" + decode-named-character-reference: "npm:^1.0.0" + mdast-util-to-string: "npm:^3.1.0" + micromark: "npm:^3.0.0" + micromark-util-decode-numeric-character-reference: "npm:^1.0.0" + micromark-util-decode-string: "npm:^1.0.0" + micromark-util-normalize-identifier: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + unist-util-stringify-position: "npm:^3.0.0" + uvu: "npm:^0.5.0" + checksum: f4e901bf2a2e93fe35a339e0cff581efacce2f7117cd5652e9a270847bd7e2508b3e717b7b4156af54d4f896d63033e06ff9fafbf59a1d46fe17dd5e2a3f7846 + languageName: node + linkType: hard + +"mdast-util-gfm-autolink-literal@npm:^1.0.0": + version: 1.0.3 + resolution: "mdast-util-gfm-autolink-literal@npm:1.0.3" + dependencies: + "@types/mdast": "npm:^3.0.0" + ccount: "npm:^2.0.0" + mdast-util-find-and-replace: "npm:^2.0.0" + micromark-util-character: "npm:^1.0.0" + checksum: 750e312eae73c3f2e8aa0e8c5232cb1b905357ff37ac236927f1af50cdbee7c2cfe2379b148ac32fa4137eeb3b24601e1bb6135084af926c7cd808867804193f + languageName: node + linkType: hard + +"mdast-util-gfm-footnote@npm:^1.0.0": + version: 1.0.2 + resolution: "mdast-util-gfm-footnote@npm:1.0.2" + dependencies: + "@types/mdast": "npm:^3.0.0" + mdast-util-to-markdown: "npm:^1.3.0" + micromark-util-normalize-identifier: "npm:^1.0.0" + checksum: 767973e46b9e2ae44e80e51a5e38ad0b032fc7f06a1a3095aa96c2886ba333941c764474a56b82e7db05efc56242a4789bc7fbbcc753d61512750e86a4192fe8 + languageName: node + linkType: hard + +"mdast-util-gfm-strikethrough@npm:^1.0.0": + version: 1.0.3 + resolution: "mdast-util-gfm-strikethrough@npm:1.0.3" + dependencies: + "@types/mdast": "npm:^3.0.0" + mdast-util-to-markdown: "npm:^1.3.0" + checksum: 29616b3dfdd33d3cd13f9b3181a8562fa2fbacfcb04a37dba3c690ba6829f0231b145444de984726d9277b2bc90dd7d96fb9df9f6292d5e77d65a8659ee2f52b + languageName: node + linkType: hard + +"mdast-util-gfm-table@npm:^1.0.0": + version: 1.0.7 + resolution: "mdast-util-gfm-table@npm:1.0.7" + dependencies: + "@types/mdast": "npm:^3.0.0" + markdown-table: "npm:^3.0.0" + mdast-util-from-markdown: "npm:^1.0.0" + mdast-util-to-markdown: "npm:^1.3.0" + checksum: a37a05a936292c4f48394123332d3c034a6e1b15bb3e7f3b94e6bce3260c9184fd388abbc4100827edd5485a6563098306994d15a729bde3c96de7a62ed5720b + languageName: node + linkType: hard + +"mdast-util-gfm-task-list-item@npm:^1.0.0": + version: 1.0.2 + resolution: "mdast-util-gfm-task-list-item@npm:1.0.2" + dependencies: + "@types/mdast": "npm:^3.0.0" + mdast-util-to-markdown: "npm:^1.3.0" + checksum: 91fa91f7d1a8797bf129008dab12d23917015ad12df00044e275b4459e8b383fbec6234338953a0089ef9c3a114d0a360c3e652eb0ebf6ece7e7a8fd3b5977c6 + languageName: node + linkType: hard + +"mdast-util-gfm@npm:^2.0.0": + version: 2.0.2 + resolution: "mdast-util-gfm@npm:2.0.2" + dependencies: + mdast-util-from-markdown: "npm:^1.0.0" + mdast-util-gfm-autolink-literal: "npm:^1.0.0" + mdast-util-gfm-footnote: "npm:^1.0.0" + mdast-util-gfm-strikethrough: "npm:^1.0.0" + mdast-util-gfm-table: "npm:^1.0.0" + mdast-util-gfm-task-list-item: "npm:^1.0.0" + mdast-util-to-markdown: "npm:^1.0.0" + checksum: 5b7f7f98a90a2962d7e0787e080c4e55b70119100c7685bbdb772d8d7865524aeffd1757edba5afba434250e0246b987c0617c2c635baaf51c26dbbb3b72dbec + languageName: node + linkType: hard + +"mdast-util-math@npm:^2.0.0": + version: 2.0.2 + resolution: "mdast-util-math@npm:2.0.2" + dependencies: + "@types/mdast": "npm:^3.0.0" + longest-streak: "npm:^3.0.0" + mdast-util-to-markdown: "npm:^1.3.0" + checksum: 2270b6f8d7f0eb7dd5c27bee8ad43f29a8e76a7092742945fd115480ddd8bf72ae53ba1f8f63697cec82016e0c169f0a201503862dfe6bc7ac2286662de3fe8e + languageName: node + linkType: hard + +"mdast-util-mdx-expression@npm:^1.0.0": + version: 1.3.2 + resolution: "mdast-util-mdx-expression@npm:1.3.2" + dependencies: + "@types/estree-jsx": "npm:^1.0.0" + "@types/hast": "npm:^2.0.0" + "@types/mdast": "npm:^3.0.0" + mdast-util-from-markdown: "npm:^1.0.0" + mdast-util-to-markdown: "npm:^1.0.0" + checksum: 01f306ee809d28825cbec23b3c80376a0fbe69601b6b2843d23beb5662a31ec7560995f52b96b13093cc03de1130404a47f139d16f58c3f54e91e88f4bdd82d2 + languageName: node + linkType: hard + +"mdast-util-mdx-jsx@npm:^2.0.0": + version: 2.1.4 + resolution: "mdast-util-mdx-jsx@npm:2.1.4" + dependencies: + "@types/estree-jsx": "npm:^1.0.0" + "@types/hast": "npm:^2.0.0" + "@types/mdast": "npm:^3.0.0" + "@types/unist": "npm:^2.0.0" + ccount: "npm:^2.0.0" + mdast-util-from-markdown: "npm:^1.1.0" + mdast-util-to-markdown: "npm:^1.3.0" + parse-entities: "npm:^4.0.0" + stringify-entities: "npm:^4.0.0" + unist-util-remove-position: "npm:^4.0.0" + unist-util-stringify-position: "npm:^3.0.0" + vfile-message: "npm:^3.0.0" + checksum: b0c16e56a99c5167e60c98dbdbe82645549630fb529688642c4664ca5557ff0b3029c75146f5657cadb7908d5fa99810eacc5dcc51676d0877c8b4dcebb11cbe + languageName: node + linkType: hard + +"mdast-util-mdx@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-mdx@npm:2.0.1" + dependencies: + mdast-util-from-markdown: "npm:^1.0.0" + mdast-util-mdx-expression: "npm:^1.0.0" + mdast-util-mdx-jsx: "npm:^2.0.0" + mdast-util-mdxjs-esm: "npm:^1.0.0" + mdast-util-to-markdown: "npm:^1.0.0" + checksum: 3b5e55781a7b7b4b7e71728a84afbec63516f251b3556efec52dbb4824c0733f5ebaa907d21211d008e5cb1a8265e6704bc062ee605f4c09e90fbfa2c6fbba3b + languageName: node + linkType: hard + +"mdast-util-mdxjs-esm@npm:^1.0.0": + version: 1.3.1 + resolution: "mdast-util-mdxjs-esm@npm:1.3.1" + dependencies: + "@types/estree-jsx": "npm:^1.0.0" + "@types/hast": "npm:^2.0.0" + "@types/mdast": "npm:^3.0.0" + mdast-util-from-markdown: "npm:^1.0.0" + mdast-util-to-markdown: "npm:^1.0.0" + checksum: 2ff0af34ea62004d39f15bd45b79e3008e68cae7e2510c9281e24a17e2c3f55d004524796166ef5aa3378798ca7f6c5f88883238f413577619bbaf41026b7e62 + languageName: node + linkType: hard + +"mdast-util-phrasing@npm:^3.0.0": + version: 3.0.1 + resolution: "mdast-util-phrasing@npm:3.0.1" + dependencies: + "@types/mdast": "npm:^3.0.0" + unist-util-is: "npm:^5.0.0" + checksum: 5e00e303652a7581593549dbce20dfb69d687d79a972f7928f6ca1920ef5385bceb737a3d5292ab6d937ed8c67bb59771e80e88f530b78734fe7d155f833e32b + languageName: node + linkType: hard + +"mdast-util-to-hast@npm:^12.1.0": + version: 12.3.0 + resolution: "mdast-util-to-hast@npm:12.3.0" + dependencies: + "@types/hast": "npm:^2.0.0" + "@types/mdast": "npm:^3.0.0" + mdast-util-definitions: "npm:^5.0.0" + micromark-util-sanitize-uri: "npm:^1.1.0" + trim-lines: "npm:^3.0.0" + unist-util-generated: "npm:^2.0.0" + unist-util-position: "npm:^4.0.0" + unist-util-visit: "npm:^4.0.0" + checksum: 0753e45bfcce423f7a13979ac720a23ed8d6bafed174c387f43bbe8baf3838f3a043cd8006975b71e5c4068b7948f83f1348acea79801101af31eaec4e7a499a + languageName: node + linkType: hard + +"mdast-util-to-hast@npm:^13.0.0": + version: 13.1.0 + resolution: "mdast-util-to-hast@npm:13.1.0" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/mdast": "npm:^4.0.0" + "@ungap/structured-clone": "npm:^1.0.0" + devlop: "npm:^1.0.0" + micromark-util-sanitize-uri: "npm:^2.0.0" + trim-lines: "npm:^3.0.0" + unist-util-position: "npm:^5.0.0" + unist-util-visit: "npm:^5.0.0" + vfile: "npm:^6.0.0" + checksum: a2b761bfae37b7eb6039e25ca2d3c4dc2f190cdef6b00e404e885d749ecc7f0ce6149f39130bdb02e122785c662eeb84dd1ac999ce3c311ffafe32ecf950071b + languageName: node + linkType: hard + +"mdast-util-to-markdown@npm:^1.0.0, mdast-util-to-markdown@npm:^1.3.0": + version: 1.5.0 + resolution: "mdast-util-to-markdown@npm:1.5.0" + dependencies: + "@types/mdast": "npm:^3.0.0" + "@types/unist": "npm:^2.0.0" + longest-streak: "npm:^3.0.0" + mdast-util-phrasing: "npm:^3.0.0" + mdast-util-to-string: "npm:^3.0.0" + micromark-util-decode-string: "npm:^1.0.0" + unist-util-visit: "npm:^4.0.0" + zwitch: "npm:^2.0.0" + checksum: 9831d14aa6c097750a90c7b87b4e814b040731c30606a794c9b136dc746633dd9ec07154ca97d4fec4eaf732cf89d14643424e2581732d6ee18c9b0e51ff7664 + languageName: node + linkType: hard + +"mdast-util-to-string@npm:^3.0.0, mdast-util-to-string@npm:^3.1.0": + version: 3.2.0 + resolution: "mdast-util-to-string@npm:3.2.0" + dependencies: + "@types/mdast": "npm:^3.0.0" + checksum: 112f4bf0f6758dcb95deffdcf37afba7eaecdfe2ee13252de031723094d4d55220e147326690a8b91244758e2d678e7aeb1fdd0fa6ef3317c979bc42effd9a21 + languageName: node + linkType: hard + +"merge2@npm:^1.3.0": + version: 1.4.1 + resolution: "merge2@npm:1.4.1" + checksum: 254a8a4605b58f450308fc474c82ac9a094848081bf4c06778200207820e5193726dc563a0d2c16468810516a5c97d9d3ea0ca6585d23c58ccfff2403e8dbbeb + languageName: node + linkType: hard + +"mermaid@npm:^10.2.2": + version: 10.7.0 + resolution: "mermaid@npm:10.7.0" + dependencies: + "@braintree/sanitize-url": "npm:^6.0.1" + "@types/d3-scale": "npm:^4.0.3" + "@types/d3-scale-chromatic": "npm:^3.0.0" + cytoscape: "npm:^3.23.0" + cytoscape-cose-bilkent: "npm:^4.1.0" + cytoscape-fcose: "npm:^2.1.0" + d3: "npm:^7.4.0" + d3-sankey: "npm:^0.12.3" + dagre-d3-es: "npm:7.0.10" + dayjs: "npm:^1.11.7" + dompurify: "npm:^3.0.5" + elkjs: "npm:^0.9.0" + khroma: "npm:^2.0.0" + lodash-es: "npm:^4.17.21" + mdast-util-from-markdown: "npm:^1.3.0" + non-layered-tidy-tree-layout: "npm:^2.0.2" + stylis: "npm:^4.1.3" + ts-dedent: "npm:^2.2.0" + uuid: "npm:^9.0.0" + web-worker: "npm:^1.2.0" + checksum: 42f1c5653b7b8954ebfa0fd26b6172d4a5834c2f87fda38aff023ccba98f3ae014c74656df3a59e2150176b670d923cdde2293dbbc6718fd812317990f389634 + languageName: node + linkType: hard + +"micromark-core-commonmark@npm:^1.0.0, micromark-core-commonmark@npm:^1.0.1": + version: 1.1.0 + resolution: "micromark-core-commonmark@npm:1.1.0" + dependencies: + decode-named-character-reference: "npm:^1.0.0" + micromark-factory-destination: "npm:^1.0.0" + micromark-factory-label: "npm:^1.0.0" + micromark-factory-space: "npm:^1.0.0" + micromark-factory-title: "npm:^1.0.0" + micromark-factory-whitespace: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-chunked: "npm:^1.0.0" + micromark-util-classify-character: "npm:^1.0.0" + micromark-util-html-tag-name: "npm:^1.0.0" + micromark-util-normalize-identifier: "npm:^1.0.0" + micromark-util-resolve-all: "npm:^1.0.0" + micromark-util-subtokenize: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.1" + uvu: "npm:^0.5.0" + checksum: b3bf7b7004ce7dbb3ae151dcca4db1d12546f1b943affb2418da4b90b9ce59357373c433ee2eea4c868aee0791dafa355aeed19f5ef2b0acaf271f32f1ecbe6a + languageName: node + linkType: hard + +"micromark-extension-gfm-autolink-literal@npm:^1.0.0": + version: 1.0.5 + resolution: "micromark-extension-gfm-autolink-literal@npm:1.0.5" + dependencies: + micromark-util-character: "npm:^1.0.0" + micromark-util-sanitize-uri: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 4964a52605ac36d24501d427e2d173fa39b5e0402275cb45068eba4898f4cb9cc57f7007b21b7514f0ab5f7b371b1701a5156a10b6ac8e77a7f36e830cf481d4 + languageName: node + linkType: hard + +"micromark-extension-gfm-footnote@npm:^1.0.0": + version: 1.1.2 + resolution: "micromark-extension-gfm-footnote@npm:1.1.2" + dependencies: + micromark-core-commonmark: "npm:^1.0.0" + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-normalize-identifier: "npm:^1.0.0" + micromark-util-sanitize-uri: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: b8090876cc3da5436c6253b0b40e39ceaa470c2429f699c19ee4163cef3102c4cd16c4ac2ec8caf916037fad310cfb52a9ef182c75d50fca7419ba08faad9b39 + languageName: node + linkType: hard + +"micromark-extension-gfm-strikethrough@npm:^1.0.0": + version: 1.0.7 + resolution: "micromark-extension-gfm-strikethrough@npm:1.0.7" + dependencies: + micromark-util-chunked: "npm:^1.0.0" + micromark-util-classify-character: "npm:^1.0.0" + micromark-util-resolve-all: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: b45fe93a7a412fc44bae7a183b92a988e17b49ed9d683bd80ee4dde96d462e1ca6b316dd64bda7759e4086d6d8686790a711e53c244f1f4d2b37e1cfe852884d + languageName: node + linkType: hard + +"micromark-extension-gfm-table@npm:^1.0.0": + version: 1.0.7 + resolution: "micromark-extension-gfm-table@npm:1.0.7" + dependencies: + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: 38b5af80ecab8206845a057338235bee6f47fb6cb904208be4b76e87906765821683e25bef85dfa485809f931eaf8cd55f16cd2f4d6e33b84f56edfaf1dfb129 + languageName: node + linkType: hard + +"micromark-extension-gfm-tagfilter@npm:^1.0.0": + version: 1.0.2 + resolution: "micromark-extension-gfm-tagfilter@npm:1.0.2" + dependencies: + micromark-util-types: "npm:^1.0.0" + checksum: 7e1bf278255cf2a8d2dda9de84bc238b39c53100e25ba8d7168220d5b00dc74869a6cb038fbf2e76b8ae89efc66906762311797a906d7d9cdd71e07bfe1ed505 + languageName: node + linkType: hard + +"micromark-extension-gfm-task-list-item@npm:^1.0.0": + version: 1.0.5 + resolution: "micromark-extension-gfm-task-list-item@npm:1.0.5" + dependencies: + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: 2179742fa2cbb243cc06bd9e43fbb94cd98e4814c9d368ddf8b4b5afa0348023f335626ae955e89d679e2c2662a7f82c315117a3b060c87bdb4420fee5a219d1 + languageName: node + linkType: hard + +"micromark-extension-gfm@npm:^2.0.0": + version: 2.0.3 + resolution: "micromark-extension-gfm@npm:2.0.3" + dependencies: + micromark-extension-gfm-autolink-literal: "npm:^1.0.0" + micromark-extension-gfm-footnote: "npm:^1.0.0" + micromark-extension-gfm-strikethrough: "npm:^1.0.0" + micromark-extension-gfm-table: "npm:^1.0.0" + micromark-extension-gfm-tagfilter: "npm:^1.0.0" + micromark-extension-gfm-task-list-item: "npm:^1.0.0" + micromark-util-combine-extensions: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 53056376d14caf3fab2cc44881c1ad49d975776cc2267bca74abda2cb31f2a77ec0fb2bdb2dd97565f0d9943ad915ff192b89c1cee5d9d727569a5e38505799b + languageName: node + linkType: hard + +"micromark-extension-math@npm:^2.0.0": + version: 2.1.2 + resolution: "micromark-extension-math@npm:2.1.2" + dependencies: + "@types/katex": "npm:^0.16.0" + katex: "npm:^0.16.0" + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: 5d40ffc93862498cbcbc9c96a40a05150b878c3d86ab25bc771dec005d286f4381578ccee3f421ecfd9db259298a89a37a5b6b48529842240d34f8acd8edffb5 + languageName: node + linkType: hard + +"micromark-extension-mdx-expression@npm:^1.0.0": + version: 1.0.8 + resolution: "micromark-extension-mdx-expression@npm:1.0.8" + dependencies: + "@types/estree": "npm:^1.0.0" + micromark-factory-mdx-expression: "npm:^1.0.0" + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-events-to-acorn: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: 99e2997a54caafc4258979c0591b3fe8e31018079df833d559768092fec41e57a71225d423f4179cea4e8bc1af2f52f5c9ae640673619d8fe142ded875240da3 + languageName: node + linkType: hard + +"micromark-extension-mdx-jsx@npm:^1.0.0": + version: 1.0.5 + resolution: "micromark-extension-mdx-jsx@npm:1.0.5" + dependencies: + "@types/acorn": "npm:^4.0.0" + "@types/estree": "npm:^1.0.0" + estree-util-is-identifier-name: "npm:^2.0.0" + micromark-factory-mdx-expression: "npm:^1.0.0" + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + vfile-message: "npm:^3.0.0" + checksum: 1b4bfbe60b9cabfabfb870f70ded8da0caacbaa3be6bdf07f6db25cc5a14c6bc970c34c60e5c80da1e97766064a117feb8160b6d661d69e530a4cc7ec97305de + languageName: node + linkType: hard + +"micromark-extension-mdx-md@npm:^1.0.0": + version: 1.0.1 + resolution: "micromark-extension-mdx-md@npm:1.0.1" + dependencies: + micromark-util-types: "npm:^1.0.0" + checksum: 9ad70b3a5e842fd7ebd93c8c48a32fd3d05fe77be06a08ef32462ea53e97d8f297e2c1c4b30a6929dbd05125279fe98bb04e9cc0bb686c691bdcf7d36c6e51b0 + languageName: node + linkType: hard + +"micromark-extension-mdxjs-esm@npm:^1.0.0": + version: 1.0.5 + resolution: "micromark-extension-mdxjs-esm@npm:1.0.5" + dependencies: + "@types/estree": "npm:^1.0.0" + micromark-core-commonmark: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-events-to-acorn: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + unist-util-position-from-estree: "npm:^1.1.0" + uvu: "npm:^0.5.0" + vfile-message: "npm:^3.0.0" + checksum: 612028bced78e882641a43c78fc4813a573b383dc0a7b90db75ed88b37bf5b5997dc7ead4a1011315b34f17bc76b7f4419de6ad9532a088102ab1eea0245d380 + languageName: node + linkType: hard + +"micromark-extension-mdxjs@npm:^1.0.0": + version: 1.0.1 + resolution: "micromark-extension-mdxjs@npm:1.0.1" + dependencies: + acorn: "npm:^8.0.0" + acorn-jsx: "npm:^5.0.0" + micromark-extension-mdx-expression: "npm:^1.0.0" + micromark-extension-mdx-jsx: "npm:^1.0.0" + micromark-extension-mdx-md: "npm:^1.0.0" + micromark-extension-mdxjs-esm: "npm:^1.0.0" + micromark-util-combine-extensions: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 3f123e4afea9674c96934c9ea6a057ec9e5584992c50c36c173a2e331d272b1f4e2a8552364a0e2cb50703d0218831fdae1a17b563f0009aac6a35350e6a7b77 + languageName: node + linkType: hard + +"micromark-factory-destination@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-destination@npm:1.1.0" + dependencies: + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 71ebd9089bf0c9689b98ef42215c04032ae2701ae08c3546b663628553255dca18e5310dbdacddad3acd8de4f12a789835fff30dadc4da3c4e30387a75e6b488 + languageName: node + linkType: hard + +"micromark-factory-label@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-label@npm:1.1.0" + dependencies: + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: 5e2cd2d8214bb92a34dfcedf9c7aecf565e3648650a3a6a0495ededf15f2318dd214dc069e3026402792cd5839d395313f8ef9c2e86ca34a8facaa0f75a77753 + languageName: node + linkType: hard + +"micromark-factory-mdx-expression@npm:^1.0.0": + version: 1.0.9 + resolution: "micromark-factory-mdx-expression@npm:1.0.9" + dependencies: + "@types/estree": "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-events-to-acorn: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + unist-util-position-from-estree: "npm:^1.0.0" + uvu: "npm:^0.5.0" + vfile-message: "npm:^3.0.0" + checksum: b28bd8e072f37ca91446fe8d113e4ae64baaef013b0cde4aa224add0ee40963ce3584b9709f7662d30491f875ae7104b897d37efa26cdaecf25082ed5bac7b8c + languageName: node + linkType: hard + +"micromark-factory-space@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-space@npm:1.1.0" + dependencies: + micromark-util-character: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 3da81187ce003dd4178c7adc4674052fb8befc8f1a700ae4c8227755f38581a4ae963866dc4857488d62d1dc9837606c9f2f435fa1332f62a0f1c49b83c6a822 + languageName: node + linkType: hard + +"micromark-factory-title@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-title@npm:1.1.0" + dependencies: + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: cf8c687d1d5c3928846a4791d4a7e2f1d7bdd2397051e20d60f06b7565a48bf85198ab6f85735e997ab3f0cbb80b8b6391f4f7ebc0aae2f2f8c3a08541257bf6 + languageName: node + linkType: hard + +"micromark-factory-whitespace@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-whitespace@npm:1.1.0" + dependencies: + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 7248cc4534f9befb38c6f398b6e38efd3199f1428fc214c9cb7ed5b6e9fa7a82c0d8cdfa9bcacde62887c9a7c8c46baf5c318b2ae8f701afbccc8ad702e92dce + languageName: node + linkType: hard + +"micromark-util-character@npm:^1.0.0": + version: 1.2.0 + resolution: "micromark-util-character@npm:1.2.0" + dependencies: + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 3390a675a50731b58a8e5493cd802e190427f10fa782079b455b00f6b54e406e36882df7d4a3bd32b709f7a2c3735b4912597ebc1c0a99566a8d8d0b816e2cd4 + languageName: node + linkType: hard + +"micromark-util-character@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-character@npm:2.0.1" + dependencies: + micromark-util-symbol: "npm:^2.0.0" + micromark-util-types: "npm:^2.0.0" + checksum: 5b91c90f29c8873a9f2f2385bbeb70f481b0e56c26092451d1796cd323257927a69eccca19b079d83d5751ec6fc92964214a3c868114555f87631426631df6b9 + languageName: node + linkType: hard + +"micromark-util-chunked@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-chunked@npm:1.1.0" + dependencies: + micromark-util-symbol: "npm:^1.0.0" + checksum: 59534cf4aaf481ed58d65478d00eae0080df9b5816673f79b5ddb0cea263e5a9ee9cbb6cc565daf1eb3c8c4ff86fc4e25d38a0577539655cda823a4249efd358 + languageName: node + linkType: hard + +"micromark-util-classify-character@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-classify-character@npm:1.1.0" + dependencies: + micromark-util-character: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 3266453dc0fdaf584e24c9b3c91d1ed180f76b5856699c51fd2549305814fcab7ec52afb4d3e83d002a9115cd2d2b2ffdc9c0b38ed85120822bf515cc00636ec + languageName: node + linkType: hard + +"micromark-util-combine-extensions@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-combine-extensions@npm:1.1.0" + dependencies: + micromark-util-chunked: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + checksum: 0bc572fab3fe77f533c29aa1b75cb847b9fc9455f67a98623ef9740b925c0b0426ad9f09bbb56f1e844ea9ebada7873d1f06d27f7c979a917692b273c4b69e31 + languageName: node + linkType: hard + +"micromark-util-decode-numeric-character-reference@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-decode-numeric-character-reference@npm:1.1.0" + dependencies: + micromark-util-symbol: "npm:^1.0.0" + checksum: 64ef2575e3fc2426976c19e16973348f20b59ddd5543f1467ac2e251f29e0a91f12089703d29ae985b0b9a408ee0d72f06d04ed3920811aa2402aabca3bdf9e4 + languageName: node + linkType: hard + +"micromark-util-decode-string@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-decode-string@npm:1.1.0" + dependencies: + decode-named-character-reference: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-decode-numeric-character-reference: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + checksum: 757a0aaa5ad6c50c7480bd75371d407ac75f5022cd4404aba07adadf1448189502aea9bb7b2d09d25e18745e0abf72b95506b6beb184bcccabe919e48e3a5df7 + languageName: node + linkType: hard + +"micromark-util-encode@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-encode@npm:1.1.0" + checksum: 9878c9bc96999d45626a7597fffac85348ea842dce75d2417345cbf070a9941c62477bd0963bef37d4f0fd29f2982be6ddf416d62806f00ccb334af9d6ee87e7 + languageName: node + linkType: hard + +"micromark-util-encode@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-encode@npm:2.0.0" + checksum: ebdaafff23100bbf4c74e63b4b1612a9ddf94cd7211d6a076bc6fb0bc32c1b48d6fb615aa0953e607c62c97d849f97f1042260d3eb135259d63d372f401bbbb2 + languageName: node + linkType: hard + +"micromark-util-events-to-acorn@npm:^1.0.0": + version: 1.2.3 + resolution: "micromark-util-events-to-acorn@npm:1.2.3" + dependencies: + "@types/acorn": "npm:^4.0.0" + "@types/estree": "npm:^1.0.0" + "@types/unist": "npm:^2.0.0" + estree-util-visit: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + vfile-message: "npm:^3.0.0" + checksum: cd3af7365806a0b22efb83cb7726cb835725c0bc22e04f7ea83f2f38a09e7132413eff6ab6d53652b969a7ec30e442731c3abbbe8a74dc2081c51fd10223c269 + languageName: node + linkType: hard + +"micromark-util-html-tag-name@npm:^1.0.0": + version: 1.2.0 + resolution: "micromark-util-html-tag-name@npm:1.2.0" + checksum: 15421869678d36b4fe51df453921e8186bff514a14e9f79f32b7e1cdd67874e22a66ad34a7f048dd132cbbbfc7c382ae2f777a2bfd1f245a47705dc1c6d4f199 + languageName: node + linkType: hard + +"micromark-util-normalize-identifier@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-normalize-identifier@npm:1.1.0" + dependencies: + micromark-util-symbol: "npm:^1.0.0" + checksum: a9657321a2392584e4d978061882117a84db7d2c2c1c052c0f5d25da089d463edb9f956d5beaf7f5768984b6f72d046d59b5972951ec7bf25397687a62b8278a + languageName: node + linkType: hard + +"micromark-util-resolve-all@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-resolve-all@npm:1.1.0" + dependencies: + micromark-util-types: "npm:^1.0.0" + checksum: b5c95484c06e87bbbb60d8430eb030a458733a5270409f4c67892d1274737087ca6a7ca888987430e57cf1dcd44bb16390d3b3936a2bf07f7534ec8f52ce43c9 + languageName: node + linkType: hard + +"micromark-util-sanitize-uri@npm:^1.0.0, micromark-util-sanitize-uri@npm:^1.1.0": + version: 1.2.0 + resolution: "micromark-util-sanitize-uri@npm:1.2.0" + dependencies: + micromark-util-character: "npm:^1.0.0" + micromark-util-encode: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + checksum: dbdb98248e9f0408c7a00f1c1cd805775b41d213defd659533835f34b38da38e8f990bf7b3f782e96bffbc549aec9c3ecdab197d4ad5adbfe08f814a70327b6e + languageName: node + linkType: hard + +"micromark-util-sanitize-uri@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-sanitize-uri@npm:2.0.0" + dependencies: + micromark-util-character: "npm:^2.0.0" + micromark-util-encode: "npm:^2.0.0" + micromark-util-symbol: "npm:^2.0.0" + checksum: 74763ca1c927dd520d3ab8fd9856a19740acf76fc091f0a1f5d4e99c8cd5f1b81c5a0be3efb564941a071fb6d85fd951103f2760eb6cff77b5ab3abe08341309 + languageName: node + linkType: hard + +"micromark-util-subtokenize@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-subtokenize@npm:1.1.0" + dependencies: + micromark-util-chunked: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.0" + uvu: "npm:^0.5.0" + checksum: f292b1b162845db50d36255c9d4c4c6d47931fbca3ac98a80c7e536d2163233fd662f8ca0479ee2b80f145c66a1394c7ed17dfce801439741211015e77e3901e + languageName: node + linkType: hard + +"micromark-util-symbol@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-symbol@npm:1.1.0" + checksum: 10ceaed33a90e6bfd3a5d57053dbb53f437d4809cc11430b5a09479c0ba601577059be9286df4a7eae6e350a60a2575dc9fa9d9872b5b8d058c875e075c33803 + languageName: node + linkType: hard + +"micromark-util-symbol@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-symbol@npm:2.0.0" + checksum: 4e76186c185ce4cefb9cea8584213d9ffacd77099d1da30c0beb09fa21f46f66f6de4c84c781d7e34ff763fe3a06b530e132fa9004882afab9e825238d0aa8b3 + languageName: node + linkType: hard + +"micromark-util-types@npm:^1.0.0, micromark-util-types@npm:^1.0.1": + version: 1.1.0 + resolution: "micromark-util-types@npm:1.1.0" + checksum: a9749cb0a12a252ff536baabcb7012421b6fad4d91a5fdd80d7b33dc7b4c22e2d0c4637dfe5b902d00247fe6c9b01f4a24fce6b572b16ccaa4da90e6ce2a11e4 + languageName: node + linkType: hard + +"micromark-util-types@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-types@npm:2.0.0" + checksum: d74e913b9b61268e0d6939f4209e3abe9dada640d1ee782419b04fd153711112cfaaa3c4d5f37225c9aee1e23c3bb91a1f5223e1e33ba92d33e83956a53e61de + languageName: node + linkType: hard + +"micromark@npm:^3.0.0": + version: 3.2.0 + resolution: "micromark@npm:3.2.0" + dependencies: + "@types/debug": "npm:^4.0.0" + debug: "npm:^4.0.0" + decode-named-character-reference: "npm:^1.0.0" + micromark-core-commonmark: "npm:^1.0.1" + micromark-factory-space: "npm:^1.0.0" + micromark-util-character: "npm:^1.0.0" + micromark-util-chunked: "npm:^1.0.0" + micromark-util-combine-extensions: "npm:^1.0.0" + micromark-util-decode-numeric-character-reference: "npm:^1.0.0" + micromark-util-encode: "npm:^1.0.0" + micromark-util-normalize-identifier: "npm:^1.0.0" + micromark-util-resolve-all: "npm:^1.0.0" + micromark-util-sanitize-uri: "npm:^1.0.0" + micromark-util-subtokenize: "npm:^1.0.0" + micromark-util-symbol: "npm:^1.0.0" + micromark-util-types: "npm:^1.0.1" + uvu: "npm:^0.5.0" + checksum: f243e805d1b3cc699fddae2de0b1492bc82462f1a709d7ae5c82039f88b1e009c959100184717e748be057b5f88603289d5681679a4e6fbabcd037beb34bc744 + languageName: node + linkType: hard + +"micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": + version: 4.0.5 + resolution: "micromatch@npm:4.0.5" + dependencies: + braces: "npm:^3.0.2" + picomatch: "npm:^2.3.1" + checksum: 3d6505b20f9fa804af5d8c596cb1c5e475b9b0cd05f652c5b56141cf941bd72adaeb7a436fda344235cef93a7f29b7472efc779fcdb83b478eab0867b95cdeff + languageName: node + linkType: hard + +"minimatch@npm:^9.0.1": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 85f407dcd38ac3e180f425e86553911d101455ca3ad5544d6a7cec16286657e4f8a9aa6695803025c55e31e35a91a2252b5dc8e7d527211278b8b65b4dbd5eac + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.4 + resolution: "minipass-fetch@npm:3.0.4" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^2.1.2" + dependenciesMeta: + encoding: + optional: true + checksum: 1b63c1f3313e88eeac4689f1b71c9f086598db9a189400e3ee960c32ed89e06737fa23976c9305c2d57464fb3fcdc12749d3378805c9d6176f5569b0d0ee8a75 + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 6c7370a6dfd257bf18222da581ba89a5eaedca10e158781232a8b5542a90547540b4b9b7e7f490e4cda43acfbd12e086f0453728ecf8c19e0ef6921bc5958ac5 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: "npm:^3.0.0" + yallist: "npm:^4.0.0" + checksum: 64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: 46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf + languageName: node + linkType: hard + +"mri@npm:^1.1.0": + version: 1.2.0 + resolution: "mri@npm:1.2.0" + checksum: a3d32379c2554cf7351db6237ddc18dc9e54e4214953f3da105b97dc3babe0deb3ffe99cf409b38ea47cc29f9430561ba6b53b24ab8f9ce97a4b50409e4a50e7 + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc + languageName: node + linkType: hard + +"mz@npm:^2.7.0": + version: 2.7.0 + resolution: "mz@npm:2.7.0" + dependencies: + any-promise: "npm:^1.0.0" + object-assign: "npm:^4.0.1" + thenify-all: "npm:^1.0.0" + checksum: 103114e93f87362f0b56ab5b2e7245051ad0276b646e3902c98397d18bb8f4a77f2ea4a2c9d3ad516034ea3a56553b60d3f5f78220001ca4c404bd711bd0af39 + languageName: node + linkType: hard + +"nanoid@npm:^3.3.6, nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: e3fb661aa083454f40500473bb69eedb85dc160e763150b9a2c567c7e9ff560ce028a9f833123b618a6ea742e311138b591910e795614a629029e86e180660f3 + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 + languageName: node + linkType: hard + +"next-mdx-remote@npm:^4.2.1": + version: 4.4.1 + resolution: "next-mdx-remote@npm:4.4.1" + dependencies: + "@mdx-js/mdx": "npm:^2.2.1" + "@mdx-js/react": "npm:^2.2.1" + vfile: "npm:^5.3.0" + vfile-matter: "npm:^3.0.1" + peerDependencies: + react: ">=16.x <=18.x" + react-dom: ">=16.x <=18.x" + checksum: d48ad271f58312d11f392b0fbd7b2dbc5990cc82fcb6d28f687875a52b28b695c0700b93f197c72910a4c73da0a1fe4867db95315bc2ee7f0fc1743279f41b80 + languageName: node + linkType: hard + +"next-seo@npm:^6.0.0": + version: 6.4.0 + resolution: "next-seo@npm:6.4.0" + peerDependencies: + next: ^8.1.1-canary.54 || >=9.0.0 + react: ">=16.0.0" + react-dom: ">=16.0.0" + checksum: 8836b84b872bee58d34cad895b0142be193bd95881cfca3f75b3b3aad67bf4542ac0a27e2285791ef6640fe808f95f01820bab167fbd26408466844c435fbdfb + languageName: node + linkType: hard + +"next-themes@npm:^0.2.1": + version: 0.2.1 + resolution: "next-themes@npm:0.2.1" + peerDependencies: + next: "*" + react: "*" + react-dom: "*" + checksum: 979dec0a2de049ce7d1b5da835e7f7dc3b7ec83ba9e464348f497a52a6a6e5b5c395c97f071f66a63f50f22cce89fb6d19061ec7e75643b0eab215b21794bde7 + languageName: node + linkType: hard + +"next@npm:^14.0.4": + version: 14.0.4 + resolution: "next@npm:14.0.4" + dependencies: + "@next/env": "npm:14.0.4" + "@next/swc-darwin-arm64": "npm:14.0.4" + "@next/swc-darwin-x64": "npm:14.0.4" + "@next/swc-linux-arm64-gnu": "npm:14.0.4" + "@next/swc-linux-arm64-musl": "npm:14.0.4" + "@next/swc-linux-x64-gnu": "npm:14.0.4" + "@next/swc-linux-x64-musl": "npm:14.0.4" + "@next/swc-win32-arm64-msvc": "npm:14.0.4" + "@next/swc-win32-ia32-msvc": "npm:14.0.4" + "@next/swc-win32-x64-msvc": "npm:14.0.4" + "@swc/helpers": "npm:0.5.2" + busboy: "npm:1.6.0" + caniuse-lite: "npm:^1.0.30001406" + graceful-fs: "npm:^4.2.11" + postcss: "npm:8.4.31" + styled-jsx: "npm:5.1.1" + watchpack: "npm:2.4.0" + peerDependencies: + "@opentelemetry/api": ^1.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + dependenciesMeta: + "@next/swc-darwin-arm64": + optional: true + "@next/swc-darwin-x64": + optional: true + "@next/swc-linux-arm64-gnu": + optional: true + "@next/swc-linux-arm64-musl": + optional: true + "@next/swc-linux-x64-gnu": + optional: true + "@next/swc-linux-x64-musl": + optional: true + "@next/swc-win32-arm64-msvc": + optional: true + "@next/swc-win32-ia32-msvc": + optional: true + "@next/swc-win32-x64-msvc": + optional: true + peerDependenciesMeta: + "@opentelemetry/api": + optional: true + sass: + optional: true + bin: + next: dist/bin/next + checksum: e6c829fd473d8c3605b2b62d15e1bf41e9d90cf59a2c213b4adeadff2846999bc9a653ffef18f6aa13cc9f5d6de02469c222acf5a4184901a4690a4504bd468f + languageName: node + linkType: hard + +"nextra-theme-docs@npm:^2.13.2": + version: 2.13.2 + resolution: "nextra-theme-docs@npm:2.13.2" + dependencies: + "@headlessui/react": "npm:^1.7.10" + "@popperjs/core": "npm:^2.11.6" + clsx: "npm:^2.0.0" + escape-string-regexp: "npm:^5.0.0" + flexsearch: "npm:^0.7.31" + focus-visible: "npm:^5.2.0" + git-url-parse: "npm:^13.1.0" + intersection-observer: "npm:^0.12.2" + match-sorter: "npm:^6.3.1" + next-seo: "npm:^6.0.0" + next-themes: "npm:^0.2.1" + scroll-into-view-if-needed: "npm:^3.0.0" + zod: "npm:^3.22.3" + peerDependencies: + next: ">=9.5.3" + nextra: 2.13.2 + react: ">=16.13.1" + react-dom: ">=16.13.1" + checksum: 94e1cf80074efd6887961459ae35f58731ccc94de5ef4a5c144f4534a62e1b099bc3c0d6a2ce6ee020984cf42e6721d0115de5cde57cbca2f4888a3489563799 + languageName: node + linkType: hard + +"nextra@npm:^2.13.2": + version: 2.13.2 + resolution: "nextra@npm:2.13.2" + dependencies: + "@headlessui/react": "npm:^1.7.10" + "@mdx-js/mdx": "npm:^2.3.0" + "@mdx-js/react": "npm:^2.3.0" + "@napi-rs/simple-git": "npm:^0.1.9" + "@theguild/remark-mermaid": "npm:^0.0.5" + "@theguild/remark-npm2yarn": "npm:^0.2.0" + clsx: "npm:^2.0.0" + github-slugger: "npm:^2.0.0" + graceful-fs: "npm:^4.2.11" + gray-matter: "npm:^4.0.3" + katex: "npm:^0.16.9" + lodash.get: "npm:^4.4.2" + next-mdx-remote: "npm:^4.2.1" + p-limit: "npm:^3.1.0" + rehype-katex: "npm:^7.0.0" + rehype-pretty-code: "npm:0.9.11" + rehype-raw: "npm:^7.0.0" + remark-gfm: "npm:^3.0.1" + remark-math: "npm:^5.1.1" + remark-reading-time: "npm:^2.0.1" + shiki: "npm:^0.14.3" + slash: "npm:^3.0.0" + title: "npm:^3.5.3" + unist-util-remove: "npm:^4.0.0" + unist-util-visit: "npm:^5.0.0" + zod: "npm:^3.22.3" + peerDependencies: + next: ">=9.5.3" + react: ">=16.13.1" + react-dom: ">=16.13.1" + checksum: 39fc0de0bc27eaca2cb8e364c55a149d65972c778846249557e218a0e316e63e38bd44c9b107159d23145c8a008c3f97c80df8aa83e390906d64b64b9327bdb6 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^3.0.0" + semver: "npm:^7.3.5" + tar: "npm:^6.1.2" + which: "npm:^4.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: abddfff7d873312e4ed4a5fb75ce893a5c4fb69e7fcb1dfa71c28a6b92a7f1ef6b62790dffb39181b5a82728ba8f2f32d229cf8cbe66769fe02cea7db4a555aa + languageName: node + linkType: hard + +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 199fc93773ae70ec9969bc6d5ac5b2bbd6eb986ed1907d751f411fef3ede0e4bfdb45ceb43711f8078bea237b6036db8b1bf208f6ff2b70c7d615afd157f3ab9 + languageName: node + linkType: hard + +"non-layered-tidy-tree-layout@npm:^2.0.2": + version: 2.0.2 + resolution: "non-layered-tidy-tree-layout@npm:2.0.2" + checksum: 73856e9959667193e733a7ef2b06a69421f4d9d7428a3982ce39763cd979a04eed0007f2afb3414afa3f6dc4dc6b5c850c2af9aa71a974475236a465093ec9c7 + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" + dependencies: + abbrev: "npm:^2.0.0" + bin: + nopt: bin/nopt.js + checksum: 9bd7198df6f16eb29ff16892c77bcf7f0cc41f9fb5c26280ac0def2cf8cf319f3b821b3af83eba0e74c85807cc430a16efe0db58fe6ae1f41e69519f585b6aff + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 + languageName: node + linkType: hard + +"normalize-range@npm:^0.1.2": + version: 0.1.2 + resolution: "normalize-range@npm:0.1.2" + checksum: bf39b73a63e0a42ad1a48c2bd1bda5a07ede64a7e2567307a407674e595bcff0fa0d57e8e5f1e7fa5e91000797c7615e13613227aaaa4d6d6e87f5bd5cc95de6 + languageName: node + linkType: hard + +"npm-run-path@npm:^2.0.0": + version: 2.0.2 + resolution: "npm-run-path@npm:2.0.2" + dependencies: + path-key: "npm:^2.0.0" + checksum: 95549a477886f48346568c97b08c4fda9cdbf7ce8a4fbc2213f36896d0d19249e32d68d7451bdcbca8041b5fba04a6b2c4a618beaf19849505c05b700740f1de + languageName: node + linkType: hard + +"npm-to-yarn@npm:^2.1.0": + version: 2.1.0 + resolution: "npm-to-yarn@npm:2.1.0" + checksum: c2a406b74d12cf5b09a2eb3c51973f1232bc023bce383d0f8442be0dc17b4618ad4fcb2f0a2beca7bef046d778eb61bfefe6b24f4ac92fd17ebaa8bd5a6a7606 + languageName: node + linkType: hard + +"object-assign@npm:^4.0.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: 1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 + languageName: node + linkType: hard + +"object-hash@npm:^3.0.0": + version: 3.0.0 + resolution: "object-hash@npm:3.0.0" + checksum: a06844537107b960c1c8b96cd2ac8592a265186bfa0f6ccafe0d34eabdb526f6fa81da1f37c43df7ed13b12a4ae3457a16071603bcd39d8beddb5f08c37b0f47 + languageName: node + linkType: hard + +"p-finally@npm:^1.0.0": + version: 1.0.0 + resolution: "p-finally@npm:1.0.0" + checksum: 6b8552339a71fe7bd424d01d8451eea92d379a711fc62f6b2fe64cad8a472c7259a236c9a22b4733abca0b5666ad503cb497792a0478c5af31ded793d00937e7 + languageName: node + linkType: hard + +"p-limit@npm:^3.1.0": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: "npm:^0.1.0" + checksum: 9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: "npm:^3.0.0" + checksum: 592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 + languageName: node + linkType: hard + +"parse-entities@npm:^4.0.0": + version: 4.0.1 + resolution: "parse-entities@npm:4.0.1" + dependencies: + "@types/unist": "npm:^2.0.0" + character-entities: "npm:^2.0.0" + character-entities-legacy: "npm:^3.0.0" + character-reference-invalid: "npm:^2.0.0" + decode-named-character-reference: "npm:^1.0.0" + is-alphanumerical: "npm:^2.0.0" + is-decimal: "npm:^2.0.0" + is-hexadecimal: "npm:^2.0.0" + checksum: 9dfa3b0dc43a913c2558c4bd625b1abcc2d6c6b38aa5724b141ed988471977248f7ad234eed57e1bc70b694dd15b0d710a04f66c2f7c096e35abd91962b7d926 + languageName: node + linkType: hard + +"parse-numeric-range@npm:^1.3.0": + version: 1.3.0 + resolution: "parse-numeric-range@npm:1.3.0" + checksum: 53465afaa92111e86697281b684aa4574427360889cc23a1c215488c06b72441febdbf09f47ab0bef9a0c701e059629f3eebd2fe6fb241a254ad7a7a642aebe8 + languageName: node + linkType: hard + +"parse-path@npm:^7.0.0": + version: 7.0.0 + resolution: "parse-path@npm:7.0.0" + dependencies: + protocols: "npm:^2.0.0" + checksum: e7646f6b998b083bbd40102643d803557ce4ae18ae1704e6cc7ae2525ea7c5400f4a3635aca3244cfe65ce4dd0ff77db1142dde4d080e8a80c364c4b3e8fe8d2 + languageName: node + linkType: hard + +"parse-url@npm:^8.1.0": + version: 8.1.0 + resolution: "parse-url@npm:8.1.0" + dependencies: + parse-path: "npm:^7.0.0" + checksum: 68b95afdf4bbf72e57c7ab66f8757c935fff888f7e2b0f1e06098b4faa19e06b6b743bddaed5bc8df4f0c2de6fc475355d787373b2fdd40092be9e4e4b996648 + languageName: node + linkType: hard + +"parse5@npm:^7.0.0": + version: 7.1.2 + resolution: "parse5@npm:7.1.2" + dependencies: + entities: "npm:^4.4.0" + checksum: 297d7af8224f4b5cb7f6617ecdae98eeaed7f8cbd78956c42785e230505d5a4f07cef352af10d3006fa5c1544b76b57784d3a22d861ae071bbc460c649482bf4 + languageName: node + linkType: hard + +"path-key@npm:^2.0.0": + version: 2.0.1 + resolution: "path-key@npm:2.0.1" + checksum: dd2044f029a8e58ac31d2bf34c34b93c3095c1481942960e84dd2faa95bbb71b9b762a106aead0646695330936414b31ca0bd862bf488a937ad17c8c5d73b32b + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 + languageName: node + linkType: hard + +"path-scurry@npm:^1.10.1": + version: 1.10.1 + resolution: "path-scurry@npm:1.10.1" + dependencies: + lru-cache: "npm:^9.1.1 || ^10.0.0" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + checksum: e5dc78a7348d25eec61ab166317e9e9c7b46818aa2c2b9006c507a6ff48c672d011292d9662527213e558f5652ce0afcc788663a061d8b59ab495681840c0c1e + languageName: node + linkType: hard + +"periscopic@npm:^3.0.0": + version: 3.1.0 + resolution: "periscopic@npm:3.1.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^3.0.0" + is-reference: "npm:^3.0.0" + checksum: fb5ce7cd810c49254cdf1cd3892811e6dd1a1dfbdf5f10a0a33fb7141baac36443c4cad4f0e2b30abd4eac613f6ab845c2bc1b7ce66ae9694c7321e6ada5bd96 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: 20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be + languageName: node + linkType: hard + +"pify@npm:^2.3.0": + version: 2.3.0 + resolution: "pify@npm:2.3.0" + checksum: 551ff8ab830b1052633f59cb8adc9ae8407a436e06b4a9718bcb27dc5844b83d535c3a8512b388b6062af65a98c49bdc0dd523d8b2617b188f7c8fee457158dc + languageName: node + linkType: hard + +"pirates@npm:^4.0.1": + version: 4.0.6 + resolution: "pirates@npm:4.0.6" + checksum: 00d5fa51f8dded94d7429700fb91a0c1ead00ae2c7fd27089f0c5b63e6eca36197fe46384631872690a66f390c5e27198e99006ab77ae472692ab9c2ca903f36 + languageName: node + linkType: hard + +"postcss-import@npm:^15.1.0": + version: 15.1.0 + resolution: "postcss-import@npm:15.1.0" + dependencies: + postcss-value-parser: "npm:^4.0.0" + read-cache: "npm:^1.0.0" + resolve: "npm:^1.1.7" + peerDependencies: + postcss: ^8.0.0 + checksum: 518aee5c83ea6940e890b0be675a2588db68b2582319f48c3b4e06535a50ea6ee45f7e63e4309f8754473245c47a0372632378d1d73d901310f295a92f26f17b + languageName: node + linkType: hard + +"postcss-js@npm:^4.0.1": + version: 4.0.1 + resolution: "postcss-js@npm:4.0.1" + dependencies: + camelcase-css: "npm:^2.0.1" + peerDependencies: + postcss: ^8.4.21 + checksum: af35d55cb873b0797d3b42529514f5318f447b134541844285c9ac31a17497297eb72296902967911bb737a75163441695737300ce2794e3bd8c70c13a3b106e + languageName: node + linkType: hard + +"postcss-load-config@npm:^4.0.1": + version: 4.0.2 + resolution: "postcss-load-config@npm:4.0.2" + dependencies: + lilconfig: "npm:^3.0.0" + yaml: "npm:^2.3.4" + peerDependencies: + postcss: ">=8.0.9" + ts-node: ">=9.0.0" + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + checksum: 3d7939acb3570b0e4b4740e483d6e555a3e2de815219cb8a3c8fc03f575a6bde667443aa93369c0be390af845cb84471bf623e24af833260de3a105b78d42519 + languageName: node + linkType: hard + +"postcss-nested@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-nested@npm:6.0.1" + dependencies: + postcss-selector-parser: "npm:^6.0.11" + peerDependencies: + postcss: ^8.2.14 + checksum: 2a50aa36d5d103c2e471954830489f4c024deed94fa066169101db55171368d5f80b32446b584029e0471feee409293d0b6b1d8ede361f6675ba097e477b3cbd + languageName: node + linkType: hard + +"postcss-selector-parser@npm:^6.0.11": + version: 6.0.15 + resolution: "postcss-selector-parser@npm:6.0.15" + dependencies: + cssesc: "npm:^3.0.0" + util-deprecate: "npm:^1.0.2" + checksum: 48b425d6cef497bcf6b7d136f6fd95cfca43026955e07ec9290d3c15457de3a862dbf251dd36f42c07a0d5b5ab6f31e41acefeff02528995a989b955505e440b + languageName: node + linkType: hard + +"postcss-value-parser@npm:^4.0.0, postcss-value-parser@npm:^4.2.0": + version: 4.2.0 + resolution: "postcss-value-parser@npm:4.2.0" + checksum: f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161 + languageName: node + linkType: hard + +"postcss@npm:8.4.31": + version: 8.4.31 + resolution: "postcss@npm:8.4.31" + dependencies: + nanoid: "npm:^3.3.6" + picocolors: "npm:^1.0.0" + source-map-js: "npm:^1.0.2" + checksum: 748b82e6e5fc34034dcf2ae88ea3d11fd09f69b6c50ecdd3b4a875cfc7cdca435c958b211e2cb52355422ab6fccb7d8f2f2923161d7a1b281029e4a913d59acf + languageName: node + linkType: hard + +"postcss@npm:^8.4.23, postcss@npm:^8.4.33": + version: 8.4.33 + resolution: "postcss@npm:8.4.33" + dependencies: + nanoid: "npm:^3.3.7" + picocolors: "npm:^1.0.0" + source-map-js: "npm:^1.0.2" + checksum: 16eda83458fcd8a91bece287b5920c7f57164c3ea293e6c80d0ea71ce7843007bcd8592260a5160b9a7f02693e6ac93e2495b02d8c7596d3f3f72c1447e3ba79 + languageName: node + linkType: hard + +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: f66430e4ff947dbb996058f6fd22de2c66612ae1a89b097744e17fb18a4e8e7a86db99eda52ccf15e53f00b63f4ec0b0911581ff2aac0355b625c8eac509b0dc + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 + languageName: node + linkType: hard + +"property-information@npm:^6.0.0": + version: 6.4.0 + resolution: "property-information@npm:6.4.0" + checksum: 48ba202f12c6abc82d37135452377dd528fae90a151bcffb28582d58d9db6e42ce835c91e2fcb12e875200b32bcaed90de4807dfb37c687f7cccf2597ccb55e1 + languageName: node + linkType: hard + +"protocols@npm:^2.0.0, protocols@npm:^2.0.1": + version: 2.0.1 + resolution: "protocols@npm:2.0.1" + checksum: 016cc58a596e401004a028a2f7005e3444bf89ee8f606409c411719374d1e8bba0464fc142a065cce0d19f41669b2f7ffe25a8bde4f16ce3b6eb01fabc51f2e7 + languageName: node + linkType: hard + +"pseudomap@npm:^1.0.2": + version: 1.0.2 + resolution: "pseudomap@npm:1.0.2" + checksum: 5a91ce114c64ed3a6a553aa7d2943868811377388bb31447f9d8028271bae9b05b340fe0b6961a64e45b9c72946aeb0a4ab635e8f7cb3715ffd0ff2beeb6a679 + languageName: node + linkType: hard + +"queue-microtask@npm:^1.2.2": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: 900a93d3cdae3acd7d16f642c29a642aea32c2026446151f0778c62ac089d4b8e6c986811076e1ae180a694cedf077d453a11b58ff0a865629a4f82ab558e102 + languageName: node + linkType: hard + +"react-dom@npm:^18.2.0": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" + dependencies: + loose-envify: "npm:^1.1.0" + scheduler: "npm:^0.23.0" + peerDependencies: + react: ^18.2.0 + checksum: 66dfc5f93e13d0674e78ef41f92ed21dfb80f9c4ac4ac25a4b51046d41d4d2186abc915b897f69d3d0ebbffe6184e7c5876f2af26bfa956f179225d921be713a + languageName: node + linkType: hard + +"react@npm:^18.2.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + dependencies: + loose-envify: "npm:^1.1.0" + checksum: b562d9b569b0cb315e44b48099f7712283d93df36b19a39a67c254c6686479d3980b7f013dc931f4a5a3ae7645eae6386b4aa5eea933baa54ecd0f9acb0902b8 + languageName: node + linkType: hard + +"read-cache@npm:^1.0.0": + version: 1.0.0 + resolution: "read-cache@npm:1.0.0" + dependencies: + pify: "npm:^2.3.0" + checksum: 90cb2750213c7dd7c80cb420654344a311fdec12944e81eb912cd82f1bc92aea21885fa6ce442e3336d9fccd663b8a7a19c46d9698e6ca55620848ab932da814 + languageName: node + linkType: hard + +"readdirp@npm:~3.6.0": + version: 3.6.0 + resolution: "readdirp@npm:3.6.0" + dependencies: + picomatch: "npm:^2.2.1" + checksum: 6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b + languageName: node + linkType: hard + +"reading-time@npm:^1.3.0": + version: 1.5.0 + resolution: "reading-time@npm:1.5.0" + checksum: 0f730852fd4fb99e5f78c5b0cf36ab8c3fa15db96f87d9563843f6fd07a47864273ade539ebb184b785b728cde81a70283aa2d9b80cba5ca03b81868be03cabc + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.14.0": + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 1b16eb2c4bceb1665c89de70dcb64126a22bc8eb958feef3cd68fe11ac6d2a4899b5cd1b80b0774c7c03591dc57d16631a7f69d2daa2ec98100e2f29f7ec4cc4 + languageName: node + linkType: hard + +"rehype-katex@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-katex@npm:7.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/katex": "npm:^0.16.0" + hast-util-from-html-isomorphic: "npm:^2.0.0" + hast-util-to-text: "npm:^4.0.0" + katex: "npm:^0.16.0" + unist-util-visit-parents: "npm:^6.0.0" + vfile: "npm:^6.0.0" + checksum: 4986d5db673576df0274464eafecef7c999fb72bf16e8df92454c68bf063b005010ab5465c64dacfbc1767ed6446dd03768917df7b9983f5e60711bce78b9880 + languageName: node + linkType: hard + +"rehype-pretty-code@npm:0.9.11": + version: 0.9.11 + resolution: "rehype-pretty-code@npm:0.9.11" + dependencies: + "@types/hast": "npm:^2.0.0" + hash-obj: "npm:^4.0.0" + parse-numeric-range: "npm:^1.3.0" + peerDependencies: + shiki: "*" + checksum: 10d9b87df6b9a963f6e650b90908347e6cce8f521bbc220ee3a101e82025d7721e2c108d90922f1a16f9d08a1b18f898ec241a12a12f5e931548e3fb528039d9 + languageName: node + linkType: hard + +"rehype-raw@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-raw@npm:7.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + hast-util-raw: "npm:^9.0.0" + vfile: "npm:^6.0.0" + checksum: 1435b4b6640a5bc3abe3b2133885c4dbff5ef2190ef9cfe09d6a63f74dd7d7ffd0cede70603278560ccf1acbfb9da9faae4b68065a28bc5aa88ad18e40f32d52 + languageName: node + linkType: hard + +"remark-gfm@npm:^3.0.1": + version: 3.0.1 + resolution: "remark-gfm@npm:3.0.1" + dependencies: + "@types/mdast": "npm:^3.0.0" + mdast-util-gfm: "npm:^2.0.0" + micromark-extension-gfm: "npm:^2.0.0" + unified: "npm:^10.0.0" + checksum: 53c4e82204f82f81949a170efdeb49d3c45137b7bca06a7ff857a483aac1a44b55ef0de8fb1bbe4f1292f2a378058e2e42e644f2c61f3e0cdc3e56afa4ec2a2c + languageName: node + linkType: hard + +"remark-math@npm:^5.1.1": + version: 5.1.1 + resolution: "remark-math@npm:5.1.1" + dependencies: + "@types/mdast": "npm:^3.0.0" + mdast-util-math: "npm:^2.0.0" + micromark-extension-math: "npm:^2.0.0" + unified: "npm:^10.0.0" + checksum: e61e314398e65d1ef9343cce37bdb8e94697772d53f1b9e48f815cece35033b4d41db81766696135558c6de40f2ad86877b49891daec6c7b1453dba0e034a9dc + languageName: node + linkType: hard + +"remark-mdx@npm:^2.0.0": + version: 2.3.0 + resolution: "remark-mdx@npm:2.3.0" + dependencies: + mdast-util-mdx: "npm:^2.0.0" + micromark-extension-mdxjs: "npm:^1.0.0" + checksum: 2688bbf03094a9cd17cc86afb6cf0270e86ffc696a2fe25ccb1befb84eb0864d281388dc560b585e05e20f94a994c9fa88492430d2ba703a2fef6918bca4c36b + languageName: node + linkType: hard + +"remark-parse@npm:^10.0.0": + version: 10.0.2 + resolution: "remark-parse@npm:10.0.2" + dependencies: + "@types/mdast": "npm:^3.0.0" + mdast-util-from-markdown: "npm:^1.0.0" + unified: "npm:^10.0.0" + checksum: 30cb8f2790380b1c7370a1c66cda41f33a7dc196b9e440a00e2675037bca55aea868165a8204e0cdbacc27ef4a3bdb7d45879826bd6efa07d9fdf328cb67a332 + languageName: node + linkType: hard + +"remark-reading-time@npm:^2.0.1": + version: 2.0.1 + resolution: "remark-reading-time@npm:2.0.1" + dependencies: + estree-util-is-identifier-name: "npm:^2.0.0" + estree-util-value-to-estree: "npm:^1.3.0" + reading-time: "npm:^1.3.0" + unist-util-visit: "npm:^3.1.0" + checksum: 9efab1883a326964822442af234c3e7776596267431edae42ac3717887af60a1cd145d07cb8a0329fb5e4cab92ae4b3ca9dc058ee453139aa2978dc4c56c4527 + languageName: node + linkType: hard + +"remark-rehype@npm:^10.0.0": + version: 10.1.0 + resolution: "remark-rehype@npm:10.1.0" + dependencies: + "@types/hast": "npm:^2.0.0" + "@types/mdast": "npm:^3.0.0" + mdast-util-to-hast: "npm:^12.1.0" + unified: "npm:^10.0.0" + checksum: 803e658c9b51a9b53ee2ada42ff82e8e570444bb97c873e0d602c2d8dcb69a774fd22bd6f26643dfd5ab4c181059ea6c9fb9a99a2d7f9665f3f11bef1a1489bd + languageName: node + linkType: hard + +"remove-accents@npm:0.4.2": + version: 0.4.2 + resolution: "remove-accents@npm:0.4.2" + checksum: 5cbc00efa52df29ce947a0c572ff975b011f5f197ebe7b4f6e527de26aba534cba12d502e3040b72e46ad01de3d4f2d5ef57a6593c964965e43ddb60438da0f8 + languageName: node + linkType: hard + +"resolve@npm:^1.1.7, resolve@npm:^1.22.2": + version: 1.22.8 + resolution: "resolve@npm:1.22.8" + dependencies: + is-core-module: "npm:^2.13.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 07e179f4375e1fd072cfb72ad66d78547f86e6196c4014b31cb0b8bb1db5f7ca871f922d08da0fbc05b94e9fd42206f819648fa3b5b873ebbc8e1dc68fec433a + languageName: node + linkType: hard + +"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin": + version: 1.22.8 + resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.13.0" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 0446f024439cd2e50c6c8fa8ba77eaa8370b4180f401a96abf3d1ebc770ac51c1955e12764cde449fde3fff480a61f84388e3505ecdbab778f4bef5f8212c729 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"reusify@npm:^1.0.4": + version: 1.0.4 + resolution: "reusify@npm:1.0.4" + checksum: c19ef26e4e188f408922c46f7ff480d38e8dfc55d448310dfb518736b23ed2c4f547fb64a6ed5bdba92cd7e7ddc889d36ff78f794816d5e71498d645ef476107 + languageName: node + linkType: hard + +"robust-predicates@npm:^3.0.0": + version: 3.0.2 + resolution: "robust-predicates@npm:3.0.2" + checksum: 4ecd53649f1c2d49529c85518f2fa69ffb2f7a4453f7fd19c042421c7b4d76c3efb48bc1c740c8f7049346d7cb58cf08ee0c9adaae595cc23564d360adb1fde4 + languageName: node + linkType: hard + +"root-workspace-0b6124@workspace:.": + version: 0.0.0-use.local + resolution: "root-workspace-0b6124@workspace:." + dependencies: + autoprefixer: "npm:^10.4.16" + next: "npm:^14.0.4" + nextra: "npm:^2.13.2" + nextra-theme-docs: "npm:^2.13.2" + postcss: "npm:^8.4.33" + react: "npm:^18.2.0" + react-dom: "npm:^18.2.0" + tailwindcss: "npm:^3.4.1" + languageName: unknown + linkType: soft + +"run-parallel@npm:^1.1.9": + version: 1.2.0 + resolution: "run-parallel@npm:1.2.0" + dependencies: + queue-microtask: "npm:^1.2.2" + checksum: 200b5ab25b5b8b7113f9901bfe3afc347e19bb7475b267d55ad0eb86a62a46d77510cb0f232507c9e5d497ebda569a08a9867d0d14f57a82ad5564d991588b39 + languageName: node + linkType: hard + +"rw@npm:1": + version: 1.3.3 + resolution: "rw@npm:1.3.3" + checksum: b1e1ef37d1e79d9dc7050787866e30b6ddcb2625149276045c262c6b4d53075ddc35f387a856a8e76f0d0df59f4cd58fe24707e40797ebee66e542b840ed6a53 + languageName: node + linkType: hard + +"sade@npm:^1.7.3": + version: 1.8.1 + resolution: "sade@npm:1.8.1" + dependencies: + mri: "npm:^1.1.0" + checksum: da8a3a5d667ad5ce3bf6d4f054bbb9f711103e5df21003c5a5c1a8a77ce12b640ed4017dd423b13c2307ea7e645adee7c2ae3afe8051b9db16a6f6d3da3f90b1 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" + dependencies: + loose-envify: "npm:^1.1.0" + checksum: b777f7ca0115e6d93e126ac490dbd82642d14983b3079f58f35519d992fa46260be7d6e6cede433a92db70306310c6f5f06e144f0e40c484199e09c1f7be53dd + languageName: node + linkType: hard + +"scroll-into-view-if-needed@npm:^3.0.0": + version: 3.1.0 + resolution: "scroll-into-view-if-needed@npm:3.1.0" + dependencies: + compute-scroll-into-view: "npm:^3.0.2" + checksum: 1f46b090e1e04fcfdef1e384f6d7e615f9f84d4176faf4dbba7347cc0a6e491e5d578eaf4dbe9618dd3d8d38efafde58535b3e00f2a21ce4178c14be364850ff + languageName: node + linkType: hard + +"section-matter@npm:^1.0.0": + version: 1.0.0 + resolution: "section-matter@npm:1.0.0" + dependencies: + extend-shallow: "npm:^2.0.1" + kind-of: "npm:^6.0.0" + checksum: 8007f91780adc5aaa781a848eaae50b0f680bbf4043b90cf8a96778195b8fab690c87fe7a989e02394ce69890e330811ec8dab22397d384673ce59f7d750641d + languageName: node + linkType: hard + +"semver@npm:^7.3.5": + version: 7.5.4 + resolution: "semver@npm:7.5.4" + dependencies: + lru-cache: "npm:^6.0.0" + bin: + semver: bin/semver.js + checksum: 5160b06975a38b11c1ab55950cb5b8a23db78df88275d3d8a42ccf1f29e55112ac995b3a26a522c36e3b5f76b0445f1eef70d696b8c7862a2b4303d7b0e7609e + languageName: node + linkType: hard + +"shebang-command@npm:^1.2.0": + version: 1.2.0 + resolution: "shebang-command@npm:1.2.0" + dependencies: + shebang-regex: "npm:^1.0.0" + checksum: 7b20dbf04112c456b7fc258622dafd566553184ac9b6938dd30b943b065b21dabd3776460df534cc02480db5e1b6aec44700d985153a3da46e7db7f9bd21326d + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^1.0.0": + version: 1.0.0 + resolution: "shebang-regex@npm:1.0.0" + checksum: 9abc45dee35f554ae9453098a13fdc2f1730e525a5eb33c51f096cc31f6f10a4b38074c1ebf354ae7bffa7229506083844008dfc3bb7818228568c0b2dc1fff2 + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"shiki@npm:^0.14.3": + version: 0.14.7 + resolution: "shiki@npm:0.14.7" + dependencies: + ansi-sequence-parser: "npm:^1.1.0" + jsonc-parser: "npm:^3.2.0" + vscode-oniguruma: "npm:^1.7.0" + vscode-textmate: "npm:^8.0.0" + checksum: 5c7fcbb870d0facccc7ae2f3410a28121f8e0b3f298e4e956de817ad6ab60a4c7e20a9184edfe50a93447addbb88b95b69e6ef88ac16ac6ca3e94c50771a6459 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.0": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: 25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 + languageName: node + linkType: hard + +"slash@npm:^3.0.0": + version: 3.0.0 + resolution: "slash@npm:3.0.0" + checksum: e18488c6a42bdfd4ac5be85b2ced3ccd0224773baae6ad42cfbb9ec74fc07f9fa8396bd35ee638084ead7a2a0818eb5e7151111544d4731ce843019dab4be47b + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.1": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:^4.3.4" + socks: "npm:^2.7.1" + checksum: a842402fc9b8848a31367f2811ca3cd14c4106588b39a0901cd7a69029998adfc6456b0203617c18ed090542ad0c24ee4e9d4c75a0c4b75071e214227c177eb7 + languageName: node + linkType: hard + +"socks@npm:^2.7.1": + version: 2.7.1 + resolution: "socks@npm:2.7.1" + dependencies: + ip: "npm:^2.0.0" + smart-buffer: "npm:^4.2.0" + checksum: 43f69dbc9f34fc8220bc51c6eea1c39715ab3cfdb115d6e3285f6c7d1a603c5c75655668a5bbc11e3c7e2c99d60321fb8d7ab6f38cda6a215fadd0d6d0b52130 + languageName: node + linkType: hard + +"sort-keys@npm:^5.0.0": + version: 5.0.0 + resolution: "sort-keys@npm:5.0.0" + dependencies: + is-plain-obj: "npm:^4.0.0" + checksum: 9f7abc51e184ef27327cb2e6da729c84d1c0223bdfc714b5065df3ff167f8e1bbdfaec6bbd41d87a308d9e79eba93c90534d034f5790b305dfbecf0701f3ee55 + languageName: node + linkType: hard + +"source-map-js@npm:^1.0.2": + version: 1.0.2 + resolution: "source-map-js@npm:1.0.2" + checksum: 32f2dfd1e9b7168f9a9715eb1b4e21905850f3b50cf02cf476e47e4eebe8e6b762b63a64357896aa29b37e24922b4282df0f492e0d2ace572b43d15525976ff8 + languageName: node + linkType: hard + +"source-map@npm:^0.7.0": + version: 0.7.4 + resolution: "source-map@npm:0.7.4" + checksum: dc0cf3768fe23c345ea8760487f8c97ef6fca8a73c83cd7c9bf2fde8bc2c34adb9c0824d6feb14bc4f9e37fb522e18af621543f1289038a66ac7586da29aa7dc + languageName: node + linkType: hard + +"space-separated-tokens@npm:^2.0.0": + version: 2.0.2 + resolution: "space-separated-tokens@npm:2.0.2" + checksum: 6173e1d903dca41dcab6a2deed8b4caf61bd13b6d7af8374713500570aa929ff9414ae09a0519f4f8772df993300305a395d4871f35bc4ca72b6db57e1f30af8 + languageName: node + linkType: hard + +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: ecadcfe4c771890140da5023d43e190b7566d9cf8b2d238600f31bec0fc653f328da4450eb04bd59a431771a8e9cc0e118f0aa3974b683a4981b4e07abc2a5bb + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.5 + resolution: "ssri@npm:10.0.5" + dependencies: + minipass: "npm:^7.0.3" + checksum: b091f2ae92474183c7ac5ed3f9811457e1df23df7a7e70c9476eaa9a0c4a0c8fc190fb45acefbf023ca9ee864dd6754237a697dc52a0fb182afe65d8e77443d8 + languageName: node + linkType: hard + +"streamsearch@npm:^1.1.0": + version: 1.1.0 + resolution: "streamsearch@npm:1.1.0" + checksum: fbd9aecc2621364384d157f7e59426f4bfd385e8b424b5aaa79c83a6f5a1c8fd2e4e3289e95de1eb3511cb96bb333d6281a9919fafce760e4edb35b2cd2facab + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: "npm:^8.0.0" + is-fullwidth-code-point: "npm:^3.0.0" + strip-ansi: "npm:^6.0.1" + checksum: 1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: "npm:^0.2.0" + emoji-regex: "npm:^9.2.2" + strip-ansi: "npm:^7.0.1" + checksum: ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca + languageName: node + linkType: hard + +"stringify-entities@npm:^4.0.0": + version: 4.0.3 + resolution: "stringify-entities@npm:4.0.3" + dependencies: + character-entities-html4: "npm:^2.0.0" + character-entities-legacy: "npm:^3.0.0" + checksum: e4582cd40b082e95bc2075bed656dcbc24e83538830f15cb5a025f1ba8d341adbdb3c66efb6a5bfd6860a3ea426322135aa666cf128bf03c961553e2f9f2d4ed + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: "npm:^5.0.1" + checksum: 1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: "npm:^6.0.1" + checksum: a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 + languageName: node + linkType: hard + +"strip-bom-string@npm:^1.0.0": + version: 1.0.0 + resolution: "strip-bom-string@npm:1.0.0" + checksum: 5c5717e2643225aa6a6d659d34176ab2657037f1fe2423ac6fcdb488f135e14fef1022030e426d8b4d0989e09adbd5c3288d5d3b9c632abeefd2358dfc512bca + languageName: node + linkType: hard + +"strip-eof@npm:^1.0.0": + version: 1.0.0 + resolution: "strip-eof@npm:1.0.0" + checksum: f336beed8622f7c1dd02f2cbd8422da9208fae81daf184f73656332899978919d5c0ca84dc6cfc49ad1fc4dd7badcde5412a063cf4e0d7f8ed95a13a63f68f45 + languageName: node + linkType: hard + +"style-to-object@npm:^0.4.1": + version: 0.4.4 + resolution: "style-to-object@npm:0.4.4" + dependencies: + inline-style-parser: "npm:0.1.1" + checksum: 3a733080da66952881175b17d65f92985cf94c1ca358a92cf21b114b1260d49b94a404ed79476047fb95698d64c7e366ca7443f0225939e2fb34c38bbc9c7639 + languageName: node + linkType: hard + +"styled-jsx@npm:5.1.1": + version: 5.1.1 + resolution: "styled-jsx@npm:5.1.1" + dependencies: + client-only: "npm:0.0.1" + peerDependencies: + react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" + peerDependenciesMeta: + "@babel/core": + optional: true + babel-plugin-macros: + optional: true + checksum: 42655cdadfa5388f8a48bb282d6b450df7d7b8cf066ac37038bd0499d3c9f084815ebd9ff9dfa12a218fd4441338851db79603498d7557207009c1cf4d609835 + languageName: node + linkType: hard + +"stylis@npm:^4.1.3": + version: 4.3.1 + resolution: "stylis@npm:4.3.1" + checksum: 33e8ebd2bfa5f0bd0215f718dc2d3be896e1d00c5bcaeb9a4ae03cf239db6867af9eee230f57229bf1c29499357073ba3e6b547484ba1db2f5de1e8be7d4eee9 + languageName: node + linkType: hard + +"sucrase@npm:^3.32.0": + version: 3.35.0 + resolution: "sucrase@npm:3.35.0" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.2" + commander: "npm:^4.0.0" + glob: "npm:^10.3.10" + lines-and-columns: "npm:^1.1.6" + mz: "npm:^2.7.0" + pirates: "npm:^4.0.1" + ts-interface-checker: "npm:^0.1.9" + bin: + sucrase: bin/sucrase + sucrase-node: bin/sucrase-node + checksum: ac85f3359d2c2ecbf5febca6a24ae9bf96c931f05fde533c22a94f59c6a74895e5d5f0e871878dfd59c2697a75ebb04e4b2224ef0bfc24ca1210735c2ec191ef + languageName: node + linkType: hard + +"supports-color@npm:^4.0.0": + version: 4.5.0 + resolution: "supports-color@npm:4.5.0" + dependencies: + has-flag: "npm:^2.0.0" + checksum: 2dc369eeac73954e87037dea1ebae0238b2abc0a39d7e35aa60eb8a84cc8d1dcade8b62e010597f5859f94c937e992abe6a6195460855fcc5e51f8cfc7fcc72a + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 + languageName: node + linkType: hard + +"tailwindcss@npm:^3.4.1": + version: 3.4.1 + resolution: "tailwindcss@npm:3.4.1" + dependencies: + "@alloc/quick-lru": "npm:^5.2.0" + arg: "npm:^5.0.2" + chokidar: "npm:^3.5.3" + didyoumean: "npm:^1.2.2" + dlv: "npm:^1.1.3" + fast-glob: "npm:^3.3.0" + glob-parent: "npm:^6.0.2" + is-glob: "npm:^4.0.3" + jiti: "npm:^1.19.1" + lilconfig: "npm:^2.1.0" + micromatch: "npm:^4.0.5" + normalize-path: "npm:^3.0.0" + object-hash: "npm:^3.0.0" + picocolors: "npm:^1.0.0" + postcss: "npm:^8.4.23" + postcss-import: "npm:^15.1.0" + postcss-js: "npm:^4.0.1" + postcss-load-config: "npm:^4.0.1" + postcss-nested: "npm:^6.0.1" + postcss-selector-parser: "npm:^6.0.11" + resolve: "npm:^1.22.2" + sucrase: "npm:^3.32.0" + bin: + tailwind: lib/cli.js + tailwindcss: lib/cli.js + checksum: eec3d758f1cd4f51ab3b4c201927c3ecd18e55f8ac94256af60276aaf8d1df78f9dddb5e9fb1e057dfa7cea3c1356add4994cc3d42da9739df874e67047e656f + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.1.2": + version: 6.2.0 + resolution: "tar@npm:6.2.0" + dependencies: + chownr: "npm:^2.0.0" + fs-minipass: "npm:^2.0.0" + minipass: "npm:^5.0.0" + minizlib: "npm:^2.1.1" + mkdirp: "npm:^1.0.3" + yallist: "npm:^4.0.0" + checksum: 02ca064a1a6b4521fef88c07d389ac0936730091f8c02d30ea60d472e0378768e870769ab9e986d87807bfee5654359cf29ff4372746cc65e30cbddc352660d8 + languageName: node + linkType: hard + +"thenify-all@npm:^1.0.0": + version: 1.6.0 + resolution: "thenify-all@npm:1.6.0" + dependencies: + thenify: "npm:>= 3.1.0 < 4" + checksum: 9b896a22735e8122754fe70f1d65f7ee691c1d70b1f116fda04fea103d0f9b356e3676cb789506e3909ae0486a79a476e4914b0f92472c2e093d206aed4b7d6b + languageName: node + linkType: hard + +"thenify@npm:>= 3.1.0 < 4": + version: 3.3.1 + resolution: "thenify@npm:3.3.1" + dependencies: + any-promise: "npm:^1.0.0" + checksum: f375aeb2b05c100a456a30bc3ed07ef03a39cbdefe02e0403fb714b8c7e57eeaad1a2f5c4ecfb9ce554ce3db9c2b024eba144843cd9e344566d9fcee73b04767 + languageName: node + linkType: hard + +"title@npm:^3.5.3": + version: 3.5.3 + resolution: "title@npm:3.5.3" + dependencies: + arg: "npm:1.0.0" + chalk: "npm:2.3.0" + clipboardy: "npm:1.2.2" + titleize: "npm:1.0.0" + bin: + title: bin/title.js + checksum: 9334ff46f49c215a108adbb3ab39bd946dfd1a669b999ad173ff61aa7598a17718f954462d8ebf8fb3ea643b5c37f2f7a163310d186acb18a101c028248d3b15 + languageName: node + linkType: hard + +"titleize@npm:1.0.0": + version: 1.0.0 + resolution: "titleize@npm:1.0.0" + checksum: 7c542bdc5754406839fc61e1a43803cb460cb0b5472f7cecf267bd9498e72d549d7f5cdfadd72ec20c3bb0783d52f4c72fe68e104cecd84195b29a5ffe836510 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: "npm:^7.0.0" + checksum: 487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 + languageName: node + linkType: hard + +"trim-lines@npm:^3.0.0": + version: 3.0.1 + resolution: "trim-lines@npm:3.0.1" + checksum: 3a1611fa9e52aa56a94c69951a9ea15b8aaad760eaa26c56a65330dc8adf99cb282fc07cc9d94968b7d4d88003beba220a7278bbe2063328eb23fb56f9509e94 + languageName: node + linkType: hard + +"trough@npm:^2.0.0": + version: 2.1.0 + resolution: "trough@npm:2.1.0" + checksum: 9a973f0745fa69b9d34f29fe8123599abb6915350a5f4e9e9c9026156219f8774af062d916f4ec327b796149188719170ad87f0d120f1e94271a1843366efcc3 + languageName: node + linkType: hard + +"ts-dedent@npm:^2.2.0": + version: 2.2.0 + resolution: "ts-dedent@npm:2.2.0" + checksum: 175adea838468cc2ff7d5e97f970dcb798bbcb623f29c6088cb21aa2880d207c5784be81ab1741f56b9ac37840cbaba0c0d79f7f8b67ffe61c02634cafa5c303 + languageName: node + linkType: hard + +"ts-interface-checker@npm:^0.1.9": + version: 0.1.13 + resolution: "ts-interface-checker@npm:0.1.13" + checksum: 232509f1b84192d07b81d1e9b9677088e590ac1303436da1e92b296e9be8e31ea042e3e1fd3d29b1742ad2c959e95afe30f63117b8f1bc3a3850070a5142fea7 + languageName: node + linkType: hard + +"tslib@npm:^2.4.0": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb + languageName: node + linkType: hard + +"type-fest@npm:^1.0.2": + version: 1.4.0 + resolution: "type-fest@npm:1.4.0" + checksum: a3c0f4ee28ff6ddf800d769eafafcdeab32efa38763c1a1b8daeae681920f6e345d7920bf277245235561d8117dab765cb5f829c76b713b4c9de0998a5397141 + languageName: node + linkType: hard + +"unified@npm:^10.0.0": + version: 10.1.2 + resolution: "unified@npm:10.1.2" + dependencies: + "@types/unist": "npm:^2.0.0" + bail: "npm:^2.0.0" + extend: "npm:^3.0.0" + is-buffer: "npm:^2.0.0" + is-plain-obj: "npm:^4.0.0" + trough: "npm:^2.0.0" + vfile: "npm:^5.0.0" + checksum: da9195e3375a74ab861a65e1d7b0454225d17a61646697911eb6b3e97de41091930ed3d167eb11881d4097c51deac407091d39ddd1ee8bf1fde3f946844a17a7 + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: "npm:^4.0.0" + checksum: 6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 + languageName: node + linkType: hard + +"unist-util-find-after@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-find-after@npm:5.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + checksum: a7cea473c4384df8de867c456b797ff1221b20f822e1af673ff5812ed505358b36f47f3b084ac14c3622cb879ed833b71b288e8aa71025352a2aab4c2925a6eb + languageName: node + linkType: hard + +"unist-util-generated@npm:^2.0.0": + version: 2.0.1 + resolution: "unist-util-generated@npm:2.0.1" + checksum: 6f052dd47a7280785f3787f52cdfe8819e1de50317a1bcf7c9346c63268cf2cebc61a5980e7ca734a54735e27dbb73091aa0361a98504ab7f9409fb75f1b16bb + languageName: node + linkType: hard + +"unist-util-is@npm:^5.0.0": + version: 5.2.1 + resolution: "unist-util-is@npm:5.2.1" + dependencies: + "@types/unist": "npm:^2.0.0" + checksum: a2376910b832bb10653d2167c3cd85b3610a5fd53f5169834c08b3c3a720fae9043d75ad32d727eedfc611491966c26a9501d428ec62467edc17f270feb5410b + languageName: node + linkType: hard + +"unist-util-is@npm:^6.0.0": + version: 6.0.0 + resolution: "unist-util-is@npm:6.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + checksum: 9419352181eaa1da35eca9490634a6df70d2217815bb5938a04af3a662c12c5607a2f1014197ec9c426fbef18834f6371bfdb6f033040fa8aa3e965300d70e7e + languageName: node + linkType: hard + +"unist-util-position-from-estree@npm:^1.0.0, unist-util-position-from-estree@npm:^1.1.0": + version: 1.1.2 + resolution: "unist-util-position-from-estree@npm:1.1.2" + dependencies: + "@types/unist": "npm:^2.0.0" + checksum: 1d95d0b2b05efcec07a4e6745a6950cd498f6100fb900615b252937baed5140df1c6319b9a67364c8a6bd891c58b3c9a52a22e8e1d3422c50bb785d7e3ad7484 + languageName: node + linkType: hard + +"unist-util-position@npm:^4.0.0": + version: 4.0.4 + resolution: "unist-util-position@npm:4.0.4" + dependencies: + "@types/unist": "npm:^2.0.0" + checksum: e506d702e25a0fb47a64502054f709a6ff5db98993bf139eec868cd11eb7de34392b781c6c2002e2c24d97aa398c14b32a47076129f36e4b894a2c1351200888 + languageName: node + linkType: hard + +"unist-util-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-position@npm:5.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + checksum: dde3b31e314c98f12b4dc6402f9722b2bf35e96a4f2d463233dd90d7cde2d4928074a7a11eff0a5eb1f4e200f27fc1557e0a64a7e8e4da6558542f251b1b7400 + languageName: node + linkType: hard + +"unist-util-remove-position@npm:^4.0.0": + version: 4.0.2 + resolution: "unist-util-remove-position@npm:4.0.2" + dependencies: + "@types/unist": "npm:^2.0.0" + unist-util-visit: "npm:^4.0.0" + checksum: 17371b1e53c52d1b00656c9c6fe1bb044846e7067022195823ed3d1a8d8b965d4f9a79b286b8a841e68731b4ec93afd563b81ae92151f80c28534ba51e9dc18f + languageName: node + linkType: hard + +"unist-util-remove-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-remove-position@npm:5.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-visit: "npm:^5.0.0" + checksum: e8c76da4399446b3da2d1c84a97c607b37d03d1d92561e14838cbe4fdcb485bfc06c06cfadbb808ccb72105a80643976d0660d1fe222ca372203075be9d71105 + languageName: node + linkType: hard + +"unist-util-remove@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-remove@npm:4.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + unist-util-visit-parents: "npm:^6.0.0" + checksum: 30f3ed31095dd7f3109266d39c514fab5f2da3fb656d5f78a0e3e7700f219760f2f4d8286c810ae43c241fee3f0a8dd40f8d1e5ebeee3cb810581d5e7e8d4f7d + languageName: node + linkType: hard + +"unist-util-stringify-position@npm:^3.0.0": + version: 3.0.3 + resolution: "unist-util-stringify-position@npm:3.0.3" + dependencies: + "@types/unist": "npm:^2.0.0" + checksum: 14550027825230528f6437dad7f2579a841780318569851291be6c8a970bae6f65a7feb24dabbcfce0e5e68cacae85bf12cbda3f360f7c873b4db602bdf7bb21 + languageName: node + linkType: hard + +"unist-util-stringify-position@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-stringify-position@npm:4.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + checksum: dfe1dbe79ba31f589108cb35e523f14029b6675d741a79dea7e5f3d098785045d556d5650ec6a8338af11e9e78d2a30df12b1ee86529cded1098da3f17ee999e + languageName: node + linkType: hard + +"unist-util-visit-parents@npm:^4.0.0": + version: 4.1.1 + resolution: "unist-util-visit-parents@npm:4.1.1" + dependencies: + "@types/unist": "npm:^2.0.0" + unist-util-is: "npm:^5.0.0" + checksum: f84b544a111af5a17f2b80c462da9f7fdcb46a69f85ab317d2d9ddca766c00e2ceea6c76c0960e58ef4607aad89661c99eccf290973b453e15dd1621c57079d4 + languageName: node + linkType: hard + +"unist-util-visit-parents@npm:^5.0.0, unist-util-visit-parents@npm:^5.1.1": + version: 5.1.3 + resolution: "unist-util-visit-parents@npm:5.1.3" + dependencies: + "@types/unist": "npm:^2.0.0" + unist-util-is: "npm:^5.0.0" + checksum: f6829bfd8f2eddf63a32e2c302cd50978ef0c194b792c6fe60c2b71dfd7232415a3c5941903972543e9d34e6a8ea69dee9ccd95811f4a795495ed2ae855d28d0 + languageName: node + linkType: hard + +"unist-util-visit-parents@npm:^6.0.0": + version: 6.0.1 + resolution: "unist-util-visit-parents@npm:6.0.1" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + checksum: 51b1a5b0aa23c97d3e03e7288f0cdf136974df2217d0999d3de573c05001ef04cccd246f51d2ebdfb9e8b0ed2704451ad90ba85ae3f3177cf9772cef67f56206 + languageName: node + linkType: hard + +"unist-util-visit@npm:^3.1.0": + version: 3.1.0 + resolution: "unist-util-visit@npm:3.1.0" + dependencies: + "@types/unist": "npm:^2.0.0" + unist-util-is: "npm:^5.0.0" + unist-util-visit-parents: "npm:^4.0.0" + checksum: 9b92ea4e6debadbb77f2c7a0ab8c8b7c63781b2f2050563c971687df368f6f6fe932d864442347a685f0dc56b570a55e5d7ffeb87a452489100640cf280dc8da + languageName: node + linkType: hard + +"unist-util-visit@npm:^4.0.0": + version: 4.1.2 + resolution: "unist-util-visit@npm:4.1.2" + dependencies: + "@types/unist": "npm:^2.0.0" + unist-util-is: "npm:^5.0.0" + unist-util-visit-parents: "npm:^5.1.1" + checksum: 56a1f49a4d8e321e75b3c7821d540a45165a031dd06324bb0e8c75e7737bc8d73bdddbf0b0ca82000f9708a4c36861c6ebe88d01f7cf00e925f5d75f13a3a017 + languageName: node + linkType: hard + +"unist-util-visit@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-visit@npm:5.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + unist-util-visit-parents: "npm:^6.0.0" + checksum: 51434a1d80252c1540cce6271a90fd1a106dbe624997c09ed8879279667fb0b2d3a685e02e92bf66598dcbe6cdffa7a5f5fb363af8fdf90dda6c855449ae39a5 + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.0.13": + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" + dependencies: + escalade: "npm:^3.1.1" + picocolors: "npm:^1.0.0" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.2": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 + languageName: node + linkType: hard + +"uuid@npm:^9.0.0": + version: 9.0.1 + resolution: "uuid@npm:9.0.1" + bin: + uuid: dist/bin/uuid + checksum: 1607dd32ac7fc22f2d8f77051e6a64845c9bce5cd3dd8aa0070c074ec73e666a1f63c7b4e0f4bf2bc8b9d59dc85a15e17807446d9d2b17c8485fbc2147b27f9b + languageName: node + linkType: hard + +"uvu@npm:^0.5.0": + version: 0.5.6 + resolution: "uvu@npm:0.5.6" + dependencies: + dequal: "npm:^2.0.0" + diff: "npm:^5.0.0" + kleur: "npm:^4.0.3" + sade: "npm:^1.7.3" + bin: + uvu: bin.js + checksum: ad32eb5f7d94bdeb71f80d073003f0138e24f61ed68cecc8e15d2f30838f44c9670577bb1775c8fac894bf93d1bc1583d470a9195e49bfa6efa14cc6f4942bff + languageName: node + linkType: hard + +"vfile-location@npm:^5.0.0": + version: 5.0.2 + resolution: "vfile-location@npm:5.0.2" + dependencies: + "@types/unist": "npm:^3.0.0" + vfile: "npm:^6.0.0" + checksum: cfc7e49de93ac5be6f3c9a9fe77676756e00d33a6c69d9c1ce279b06eedafa67fe5d0da2334b40e97963c43b014501bca2f829dfd6622a3290fb6f7dd2b9339e + languageName: node + linkType: hard + +"vfile-matter@npm:^3.0.1": + version: 3.0.1 + resolution: "vfile-matter@npm:3.0.1" + dependencies: + "@types/js-yaml": "npm:^4.0.0" + is-buffer: "npm:^2.0.0" + js-yaml: "npm:^4.0.0" + checksum: 45ff9b49e7a5817b646d76f14d2486e12a93a16951bd8cfa6c64f0c78c4e56e48d30a0542a980bc9c7aae1bb430d457f9dfc2677e514d66cc2976ab31f10403a + languageName: node + linkType: hard + +"vfile-message@npm:^3.0.0": + version: 3.1.4 + resolution: "vfile-message@npm:3.1.4" + dependencies: + "@types/unist": "npm:^2.0.0" + unist-util-stringify-position: "npm:^3.0.0" + checksum: c4ccf9c0ced92d657846fd067fefcf91c5832cdbe2ecc431bb67886e8c959bf7fc05a9dbbca5551bc34c9c87a0a73854b4249f65c64ddfebc4d59ea24a18b996 + languageName: node + linkType: hard + +"vfile-message@npm:^4.0.0": + version: 4.0.2 + resolution: "vfile-message@npm:4.0.2" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-stringify-position: "npm:^4.0.0" + checksum: 07671d239a075f888b78f318bc1d54de02799db4e9dce322474e67c35d75ac4a5ac0aaf37b18801d91c9f8152974ea39678aa72d7198758b07f3ba04fb7d7514 + languageName: node + linkType: hard + +"vfile@npm:^5.0.0, vfile@npm:^5.3.0": + version: 5.3.7 + resolution: "vfile@npm:5.3.7" + dependencies: + "@types/unist": "npm:^2.0.0" + is-buffer: "npm:^2.0.0" + unist-util-stringify-position: "npm:^3.0.0" + vfile-message: "npm:^3.0.0" + checksum: c36bd4c3f16ec0c6cbad0711ca99200316bbf849d6b07aa4cb5d9062cc18ae89249fe62af9521926e9659c0e6bc5c2c1da0fe26b41fb71e757438297e1a41da4 + languageName: node + linkType: hard + +"vfile@npm:^6.0.0": + version: 6.0.1 + resolution: "vfile@npm:6.0.1" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-stringify-position: "npm:^4.0.0" + vfile-message: "npm:^4.0.0" + checksum: 443bda43e5ad3b73c5976e987dba2b2d761439867ba7d5d7c5f4b01d3c1cb1b976f5f0e6b2399a00dc9b4eaec611bd9984ce9ce8a75a72e60aed518b10a902d2 + languageName: node + linkType: hard + +"vscode-oniguruma@npm:^1.7.0": + version: 1.7.0 + resolution: "vscode-oniguruma@npm:1.7.0" + checksum: bef0073c665ddf8c86e51da94529c905856559e9aba97a9882f951acd572da560384775941ab6e7e8db94d9c578b25fefb951e4b73c37e8712e16b0231de2689 + languageName: node + linkType: hard + +"vscode-textmate@npm:^8.0.0": + version: 8.0.0 + resolution: "vscode-textmate@npm:8.0.0" + checksum: 836f7fe73fc94998a38ca193df48173a2b6eab08b4943d83c8cac9a2a0c3546cfdab4cf1b10b890ec4a4374c5bee03a885ef0e83e7fd2bd618cf00781c017c04 + languageName: node + linkType: hard + +"watchpack@npm:2.4.0": + version: 2.4.0 + resolution: "watchpack@npm:2.4.0" + dependencies: + glob-to-regexp: "npm:^0.4.1" + graceful-fs: "npm:^4.1.2" + checksum: c5e35f9fb9338d31d2141d9835643c0f49b5f9c521440bb648181059e5940d93dd8ed856aa8a33fbcdd4e121dad63c7e8c15c063cf485429cd9d427be197fe62 + languageName: node + linkType: hard + +"web-namespaces@npm:^2.0.0": + version: 2.0.1 + resolution: "web-namespaces@npm:2.0.1" + checksum: df245f466ad83bd5cd80bfffc1674c7f64b7b84d1de0e4d2c0934fb0782e0a599164e7197a4bce310ee3342fd61817b8047ff04f076a1ce12dd470584142a4bd + languageName: node + linkType: hard + +"web-worker@npm:^1.2.0": + version: 1.3.0 + resolution: "web-worker@npm:1.3.0" + checksum: bca341b421f07c2d33aa205d463e6a2d3d376fb0628a01052dc343fd88a1d688df58d1c7fe36f631d0d860bbd3060f5014cca67d6f8781634b6c2fae25d1fc70 + languageName: node + linkType: hard + +"which@npm:^1.2.9": + version: 1.3.1 + resolution: "which@npm:1.3.1" + dependencies: + isexe: "npm:^2.0.0" + bin: + which: ./bin/which + checksum: e945a8b6bbf6821aaaef7f6e0c309d4b615ef35699576d5489b4261da9539f70393c6b2ce700ee4321c18f914ebe5644bc4631b15466ffbaad37d83151f6af59 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: "npm:^6.1.0" + string-width: "npm:^5.0.1" + strip-ansi: "npm:^7.0.1" + checksum: 138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 + languageName: node + linkType: hard + +"yallist@npm:^2.1.2": + version: 2.1.2 + resolution: "yallist@npm:2.1.2" + checksum: 0b9e25aa00adf19e01d2bcd4b208aee2b0db643d9927131797b7af5ff69480fc80f1c3db738cbf3946f0bddf39d8f2d0a5709c644fd42d4aa3a4e6e786c087b5 + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a + languageName: node + linkType: hard + +"yaml@npm:^2.3.4": + version: 2.3.4 + resolution: "yaml@npm:2.3.4" + checksum: cf03b68f8fef5e8516b0f0b54edaf2459f1648317fc6210391cf606d247e678b449382f4bd01f77392538429e306c7cba8ff46ff6b37cac4de9a76aff33bd9e1 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f + languageName: node + linkType: hard + +"zod@npm:^3.22.3": + version: 3.22.4 + resolution: "zod@npm:3.22.4" + checksum: 7578ab283dac0eee66a0ad0fc4a7f28c43e6745aadb3a529f59a4b851aa10872b3890398b3160f257f4b6817b4ce643debdda4fb21a2c040adda7862cab0a587 + languageName: node + linkType: hard + +"zwitch@npm:^2.0.0": + version: 2.0.4 + resolution: "zwitch@npm:2.0.4" + checksum: 3c7830cdd3378667e058ffdb4cf2bb78ac5711214e2725900873accb23f3dfe5f9e7e5a06dcdc5f29605da976fc45c26d9a13ca334d6eea2245a15e77b8fc06e + languageName: node + linkType: hard diff --git a/example/dart/convert.dart b/example/dart/convert.dart new file mode 100644 index 0000000..c0be5de --- /dev/null +++ b/example/dart/convert.dart @@ -0,0 +1,29 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:kubeconfig/kubeconfig.dart'; + +Future main() async { + try { + final kubeconfigJson = await File('test/files/valid.json').readAsString(); + final kubeconfig = Kubeconfig.fromJson( + json.decode(kubeconfigJson) as Map, + ); + final kubeconfigYaml = kubeconfig.toYaml(); + + print(kubeconfigYaml); + exit(0); + } on FormatException { + print('Invalid JSON content.'); + exit(65); + } on FileSystemException { + print('File does not exist or could not be read.'); + exit(74); + } catch (e) { + print('An unexpected error occurred.'); + exit(70); + } +} + +// ignore_for_file: avoid_print diff --git a/example/dart/merge.dart b/example/dart/merge.dart new file mode 100644 index 0000000..cdc3f58 --- /dev/null +++ b/example/dart/merge.dart @@ -0,0 +1,32 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:kubeconfig/kubeconfig.dart'; + +Future main() async { + try { + final yaml1 = await File('test/files/valid_multi.yaml').readAsString(); + final yaml2 = await File('test/files/valid.yaml').readAsString(); + final kubeconfig1 = Kubeconfig.fromYaml(yaml1); + final kubeconfig2 = Kubeconfig.fromYaml(yaml2); + final kubeconfigMerged = kubeconfig1.merge(kubeconfig2); + + if (kubeconfigMerged != null) { + print('Context Count: ${kubeconfigMerged.contexts?.length}'); + } else { + print('Cannot merged. One or both kubeconfig is not valid.'); + } + exit(0); + } on YamlException { + print('Invalid YAML content.'); + exit(65); + } on FileSystemException { + print('File does not exist or could not be read.'); + exit(74); + } catch (e) { + print('An unexpected error occurred.'); + exit(70); + } +} + +// ignore_for_file: avoid_print diff --git a/example/dart/validate.dart b/example/dart/validate.dart new file mode 100644 index 0000000..cd6e7f0 --- /dev/null +++ b/example/dart/validate.dart @@ -0,0 +1,30 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:kubeconfig/kubeconfig.dart'; + +Future main() async { + try { + final kubeconfigYaml = await File('test/files/valid.yaml').readAsString(); + final kubeconfig = Kubeconfig.fromYaml(kubeconfigYaml); + final validationResult = kubeconfig.validate(); + + if (validationResult.code == ValidationCode.valid) { + print('Context Count: ${kubeconfig.contexts?.length}'); + } else { + print('Error: ${validationResult.description}'); + } + exit(0); + } on YamlException { + print('Invalid YAML content.'); + exit(65); + } on FileSystemException { + print('File does not exist or could not be read.'); + exit(74); + } catch (e) { + print('An unexpected error occurred.'); + exit(70); + } +} + +// ignore_for_file: avoid_print diff --git a/example/example.dart b/example/example.dart new file mode 100644 index 0000000..c015fcb --- /dev/null +++ b/example/example.dart @@ -0,0 +1,17 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:kubeconfig/kubeconfig.dart'; + +Future main() async { + final kubeconfigYaml = + await File('test/files/invalid_current_context.yaml').readAsString(); + final kubeconfig = Kubeconfig.fromYaml(kubeconfigYaml); + final validationResult = kubeconfig.validate(); + + if (validationResult.code != ValidationCode.valid) { + print('${validationResult.description}'); + } +} + +// ignore_for_file: avoid_print diff --git a/example/js/convert.js b/example/js/convert.js new file mode 100644 index 0000000..efd3f7f --- /dev/null +++ b/example/js/convert.js @@ -0,0 +1 @@ +// TODO: TBD diff --git a/example/js/merge.js b/example/js/merge.js new file mode 100644 index 0000000..efd3f7f --- /dev/null +++ b/example/js/merge.js @@ -0,0 +1 @@ +// TODO: TBD diff --git a/example/js/validate.js b/example/js/validate.js new file mode 100644 index 0000000..efd3f7f --- /dev/null +++ b/example/js/validate.js @@ -0,0 +1 @@ +// TODO: TBD diff --git a/lib/kubeconfig.dart b/lib/kubeconfig.dart new file mode 100644 index 0000000..ea81e37 --- /dev/null +++ b/lib/kubeconfig.dart @@ -0,0 +1,9 @@ +/// Kubeconfig utility +library kubeconfig; + +export 'package:yaml/src/yaml_exception.dart'; + +export 'src/enums/enums.dart'; +export 'src/exceptions/exceptions.dart'; +export 'src/extensions/extensions.dart'; +export 'src/models/models.dart'; diff --git a/lib/src/enums/enums.dart b/lib/src/enums/enums.dart new file mode 100644 index 0000000..598648d --- /dev/null +++ b/lib/src/enums/enums.dart @@ -0,0 +1,2 @@ +export 'interactive_mode.dart'; +export 'validation_code.dart'; diff --git a/lib/src/enums/interactive_mode.dart b/lib/src/enums/interactive_mode.dart new file mode 100644 index 0000000..0dfeb15 --- /dev/null +++ b/lib/src/enums/interactive_mode.dart @@ -0,0 +1,26 @@ +/// {@template interactive_mode} +/// ExecInteractiveMode is a string that describes an exec plugin's +/// relationship with standard input. +/// {@endtemplate} +enum InteractiveMode { + /// AlwaysExecInteractiveMode declares that this exec plugin requires + /// standard input in order to run, and therefore the exec plugin will only + /// be run if standard input is available for user input. If standard input + /// is not available for user input, then the exec plugin will not be run and + /// an error will be returned by the exec plugin runner. + Always, + + /// IfAvailableExecInteractiveMode declares that this exec plugin would like + /// to use standard input if it is available, but can still operate if + /// standard input is not available. Therefore, the exec plugin will be run + /// regardless of whether stdin is available for user input. If standard input + /// is available for user input, then it will be provided to this exec plugin. + IfAvailable, + + /// NeverExecInteractiveMode declares that this exec plugin never needs to + /// use standard input, and therefore the exec plugin will be run regardless + /// of whether standard input is available for user input. + Never, +} + +// ignore_for_file: constant_identifier_names diff --git a/lib/src/enums/validation_code.dart b/lib/src/enums/validation_code.dart new file mode 100644 index 0000000..1442f49 --- /dev/null +++ b/lib/src/enums/validation_code.dart @@ -0,0 +1,117 @@ +/// {@template validation_code} +/// Kubeconfig validation code. +/// {@endtemplate} +enum ValidationCode { + /// Kubeconfig is valid + valid, + + /// "clusters" was not found + clustersRequired, + + /// "contexts" was not found + contextsRequired, + + /// "users" was not found + usersRequired, + + /// "name" is required for a named cluster + nameRequiredForNamedCluster, + + /// "name" is required for a named context + nameRequiredForNamedContext, + + /// "name" is required for a named user + nameRequiredForNamedUser, + + /// "cluster" is required for a named cluster + clusterRequiredForNamedCluster, + + /// "context" is required for a named context + contextRequiredForNamedContext, + + /// "user" is required for a named user + userRequiredForNamedUser, + + /// "server" is required for a cluster + serverRequiredForCluster, + + /// "cluster" is required for a context + clusterRequiredForContext, + + /// "user" is required for a context + userRequiredForContext, + + /// No more than one cluster with the same name + namedClusterDuplicate, + + /// No more than one context with the same name + namedContextDuplicate, + + /// No more than one user with the same name + namedUserDuplicate, + + /// Current context was not found + currentContextNotFound, + + /// cluster "x" was not found for context "y" + clusterNotFoundForContext, + + /// user "x" was not found for context "y" + userNotFoundForContext, + + /// namespace "x" for context "y" max length cannot be greater than 63 + namespaceInvalidMaxLengthForContext, + + /// namespace "x" for context "y" must be lower case alphanumeric characters + /// with dash + namespaceFormatNotMatchForContext, + + /// certificate-authority-data and certificate-authority are both specified + /// for "x" + certificateAuthorityErrorForCluster, + + /// Unable to read certificate-authority "x" for "y" + certificateAuthorityFileErrorForCluster, + + /// Invalid proxy-url for "x" + proxyUrlInvalidForCluster, + + /// Unsupported proxy-url scheme "x", must be http, https, or socks5 for "y" + proxyUrlInvalidSchemeForCluster, + + /// client-cert-data and client-cert are both specified for "x" + clientCertErrorForUser, + + /// client-key-data and client-key are both specified for "x" + clientKeyErrorForUser, + + /// client-key-data or client-key must be specified for "x" to use the + /// clientCert auth method + clientKeyNotFoundForUser, + + /// Unable to read client-cert "x" for "y" + clientCertFileErrorForUser, + + /// Unable to read client-key "x" for "y" + clientKeyFileErrorForUser, + + /// authProvider cannot be provided in combination with an exec plugin for "x" + authProviderAndExecErrorForUser, + + /// command must be specified for "x" to use exec authentication plugin + execCommandNotFoundForUser, + + /// apiVersion must be specified for "x" to use exec authentication plugin + execApiVersionNotFoundForUser, + + /// env variable name must be specified for "x" to use exec authentication + /// plugin + execEnvNameNotFoundForUser, + + /// More than one authentication method found for "x"; found + /// (token, basicAuth), only one is allowed + moreThanOneAuthFoundForUser, + + /// Requesting uid, groups or user-extra for "x" without impersonating a user + impersonatingErrorForUser, +} diff --git a/lib/src/exceptions/exceptions.dart b/lib/src/exceptions/exceptions.dart new file mode 100644 index 0000000..1099493 --- /dev/null +++ b/lib/src/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'kubeconfig_exception.dart'; diff --git a/lib/src/exceptions/kubeconfig_exception.dart b/lib/src/exceptions/kubeconfig_exception.dart new file mode 100644 index 0000000..0d0224a --- /dev/null +++ b/lib/src/exceptions/kubeconfig_exception.dart @@ -0,0 +1,244 @@ +import 'package:equatable/equatable.dart'; +import 'package:kubeconfig/src/enums/validation_code.dart'; + +/// {@template kubeconfig_exception} +/// Kubeconfig exception. +/// {@endtemplate} +class KubeconfigException extends Equatable implements Exception { + /// {@macro kubeconfig_exception} + const KubeconfigException({ + required this.code, + this.message, + }); + + /// Exception validation code. + final ValidationCode code; + + /// Exception message. + final String? message; + + @override + List get props => [ + code, + message, + ]; + + @override + bool get stringify => true; +} + +/// {@template required_exception} +/// Required exception. +/// {@endtemplate} +class RequiredException extends KubeconfigException { + /// {@macro required_exception} + const RequiredException({required super.code, super.message}); +} + +/// {@template named_cluster_duplicate} +/// Named cluster is duplicate exception. +/// {@endtemplate} +class NamedClusterDuplicateException extends KubeconfigException { + /// {@macro named_cluster_duplicate} + const NamedClusterDuplicateException({super.message}) + : super(code: ValidationCode.namedClusterDuplicate); +} + +/// {@template named_context_duplicate} +/// Named context is duplicate exception. +/// {@endtemplate} +class NamedContextDuplicateException extends KubeconfigException { + /// {@macro named_context_duplicate} + const NamedContextDuplicateException({super.message}) + : super(code: ValidationCode.namedContextDuplicate); +} + +/// {@template named_user_duplicate} +// Named user is duplicate exception. +/// {@endtemplate} +class NamedUserDuplicateException extends KubeconfigException { + /// {@macro named_user_duplicate} + const NamedUserDuplicateException({super.message}) + : super(code: ValidationCode.namedUserDuplicate); +} + +/// {@template current_context_not_found} +// Current context not found exception. +/// {@endtemplate} +class CurrentContextNotFoundException extends KubeconfigException { + /// {@macro current_context_not_found} + const CurrentContextNotFoundException({super.message}) + : super(code: ValidationCode.currentContextNotFound); +} + +/// {@template cluster_not_found_for_context} +/// Cluster not found for context exception. +/// {@endtemplate} +class ClusterNotFoundForContextException extends KubeconfigException { + /// {@macro cluster_not_found_for_context} + const ClusterNotFoundForContextException({super.message}) + : super(code: ValidationCode.clusterNotFoundForContext); +} + +/// {@template user_not_found_for_context} +/// User not found for context exception. +/// {@endtemplate} +class UserNotFoundForContextException extends KubeconfigException { + /// {@macro user_not_found_for_context} + const UserNotFoundForContextException({super.message}) + : super(code: ValidationCode.userNotFoundForContext); +} + +/// {@template namespace_invalid_max_length_for_context} +/// Namespace invalid max length for context exception. +/// {@endtemplate} +class NamespaceInvalidMaxLengthForContextException extends KubeconfigException { + /// {@macro namespace_invalid_max_length_for_context} + const NamespaceInvalidMaxLengthForContextException({super.message}) + : super(code: ValidationCode.namespaceInvalidMaxLengthForContext); +} + +/// {@template namespace_format_not_match_for_context} +/// Namespace format not match for context exception. +/// {@endtemplate} +class NamespaceFormatNotMatchForContextException extends KubeconfigException { + /// {@macro namespace_format_not_match_for_context} + const NamespaceFormatNotMatchForContextException({super.message}) + : super(code: ValidationCode.namespaceFormatNotMatchForContext); +} + +/// {@template certificate_authority_error_for_cluster} +/// Certificate authority error for cluster exception. +/// {@endtemplate} +class CertificateAuthorityErrorForClusterException extends KubeconfigException { + /// {@macro certificate_authority_error_for_cluster} + const CertificateAuthorityErrorForClusterException({super.message}) + : super(code: ValidationCode.certificateAuthorityErrorForCluster); +} + +/// {@template certificate_authority_file_error_for_cluster} +/// Certificate authority file error for cluster exception. +/// {@endtemplate} +class CertificateAuthorityFileErrorForClusterException + extends KubeconfigException { + /// {@macro certificate_authority_file_error_for_cluster} + const CertificateAuthorityFileErrorForClusterException({super.message}) + : super(code: ValidationCode.certificateAuthorityFileErrorForCluster); +} + +/// {@template proxy_url_invalid_for_cluster} +/// Proxy url invalid for cluster exception. +/// {@endtemplate} +class ProxyUrlInvalidForClusterException extends KubeconfigException { + /// {@macro proxy_url_invalid_for_cluster} + const ProxyUrlInvalidForClusterException({super.message}) + : super(code: ValidationCode.proxyUrlInvalidForCluster); +} + +/// {@template proxy_url_invalid_scheme_for_cluster} +/// Proxy url invalid scheme for cluster exception. +/// {@endtemplate} +class ProxyUrlInvalidSchemeForClusterException extends KubeconfigException { + /// {@macro proxy_url_invalid_scheme_for_cluster} + const ProxyUrlInvalidSchemeForClusterException({super.message}) + : super(code: ValidationCode.proxyUrlInvalidSchemeForCluster); +} + +/// {@template client_cert_error_for_user} +/// Client cert error for user exception. +/// {@endtemplate} +class ClientCertErrorForUserException extends KubeconfigException { + /// {@macro client_cert_error_for_user} + const ClientCertErrorForUserException({super.message}) + : super(code: ValidationCode.clientCertErrorForUser); +} + +/// {@template client_key_error_for_user} +/// Client key error for user exception. +/// {@endtemplate} +class ClientKeyErrorForUserException extends KubeconfigException { + /// {@macro client_key_error_for_user} + const ClientKeyErrorForUserException({super.message}) + : super(code: ValidationCode.clientKeyErrorForUser); +} + +/// {@template client_key_not_found_for_user} +/// Client key not found for user exception. +/// {@endtemplate} +class ClientKeyNotFoundForUserException extends KubeconfigException { + /// {@macro client_key_not_found_for_user} + const ClientKeyNotFoundForUserException({super.message}) + : super(code: ValidationCode.clientKeyNotFoundForUser); +} + +/// {@template client_cert_file_error_for_user} +/// Client cert file error for user exception. +/// {@endtemplate} +class ClientCertFileErrorForUserException extends KubeconfigException { + /// {@macro client_cert_file_error_for_user} + const ClientCertFileErrorForUserException({super.message}) + : super(code: ValidationCode.clientCertFileErrorForUser); +} + +/// {@template client_key_file_error_for_user} +/// Client key file error for user exception. +/// {@endtemplate} +class ClientKeyFileErrorForUserException extends KubeconfigException { + /// {@macro client_key_file_error_for_user} + const ClientKeyFileErrorForUserException({super.message}) + : super(code: ValidationCode.clientKeyFileErrorForUser); +} + +/// {@template auth_provider_and_exec_error_for_user} +/// Auth provider and exec error for user exception. +/// {@endtemplate} +class AuthProviderAndExecErrorForUserException extends KubeconfigException { + /// {@macro auth_provider_and_exec_error_for_user} + const AuthProviderAndExecErrorForUserException({super.message}) + : super(code: ValidationCode.authProviderAndExecErrorForUser); +} + +/// {@template exec_command_not_found_for_user} +/// Exec command not found for user exception. +/// {@endtemplate} +class ExecCommandNotFoundForUserException extends KubeconfigException { + /// {@macro exec_command_not_found_for_user} + const ExecCommandNotFoundForUserException({super.message}) + : super(code: ValidationCode.execCommandNotFoundForUser); +} + +/// {@template exec_api_version_not_found_for_user} +/// Exec apiVersion not found for user exception. +/// {@endtemplate} +class ExecApiVersionNotFoundForUserException extends KubeconfigException { + /// {@macro exec_api_version_not_found_for_user} + const ExecApiVersionNotFoundForUserException({super.message}) + : super(code: ValidationCode.execApiVersionNotFoundForUser); +} + +/// {@template exec_env_name_not_found_for_user} +/// Exec env name not found for user exception. +/// {@endtemplate} +class ExecEnvNameNotFoundForUserException extends KubeconfigException { + /// {@macro exec_env_name_not_found_for_user} + const ExecEnvNameNotFoundForUserException({super.message}) + : super(code: ValidationCode.execEnvNameNotFoundForUser); +} + +/// {@template more_than_one_auth_found_for_user} +/// More than one auth found for user exception. +/// {@endtemplate} +class MoreThanOneAuthFoundForUserException extends KubeconfigException { + /// {@macro more_than_one_auth_found_for_user} + const MoreThanOneAuthFoundForUserException({super.message}) + : super(code: ValidationCode.moreThanOneAuthFoundForUser); +} + +/// {@template impersonating_error_for_user} +/// Impersonating error for user exception. +/// {@endtemplate} +class ImpersonatingErrorForUserException extends KubeconfigException { + /// {@macro impersonating_error_for_user} + const ImpersonatingErrorForUserException({super.message}) + : super(code: ValidationCode.impersonatingErrorForUser); +} diff --git a/lib/src/extensions/extensions.dart b/lib/src/extensions/extensions.dart new file mode 100644 index 0000000..0348c32 --- /dev/null +++ b/lib/src/extensions/extensions.dart @@ -0,0 +1,2 @@ +export 'object_extensions.dart'; +export 'string_extensions.dart'; diff --git a/lib/src/extensions/object_extensions.dart b/lib/src/extensions/object_extensions.dart new file mode 100644 index 0000000..af8a5f9 --- /dev/null +++ b/lib/src/extensions/object_extensions.dart @@ -0,0 +1,146 @@ +/// Json convert extensions +extension JsonConvertX on Map { + /// Converts JSON to YAML. + String toYaml() => _condense( + _formatObject( + value: this, + context: const _Context( + nesting: 0, + ), + ), + ); +} + +String _formatObject({required dynamic value, required _Context context}) { + if (value is Map) { + return _formatStructure( + structure: value as Map, + context: context, + ); + } else if (value is Iterable) { + return _formatCollection(collection: value, context: context); + } else if (value is String) { + return _isMultilineString(value) + ? _formatMultilineString(value, context) + : _formatSingleLineString(value, context); + } else if (value == null) { + return ''; + } else { + return '$value'; + } +} + +String _formatStructure({ + required Map structure, + required _Context context, +}) { + if (structure.isEmpty) return '{}'; + + String separator_(MapEntry e) { + return e.value is Map && (e.value as Map).isNotEmpty + ? '\n${_indentation(context.nest())}' + : ' '; + } + + final entries = structure.entries; + final firstElement = entries.first; + final first = '${firstElement.key}:${separator_(firstElement)}' + '${_formatObject(value: firstElement.value, context: context.nest())}\n'; + final rest = entries + .skip(1) + .map( + (e) => '${_indentation(context)}${e.key}:${separator_(e)}' + '${_formatObject(value: e.value, context: context.nest())}', + ) + .join('\n'); + + return '$first$rest'; +} + +String _formatCollection({ + required Iterable collection, + required _Context context, +}) { + if (collection.isEmpty) return ''; + + return '\n${collection.map( + (dynamic e) => '${_indentation(context)}- ' + '${_formatObject( + value: e, + context: context.nest(), + )}', + ).join('\n')}\n'; +} + +String _condense(String yaml) => _endWithEol( + yaml + .split('\n') + .map((s) => s.trimRight()) + .where((s) => s.isNotEmpty) + .join('\n'), + ); + +String _endWithEol(String s) => '$s\n'; + +class _Context { + const _Context({ + required this.nesting, + }); + + final int nesting; + + _Context nest() => _Context(nesting: nesting + 1); +} + +const _spacesPerNestingLevel = 2; +String _indentation(_Context ctx) => ''.padLeft( + ctx.nesting * _spacesPerNestingLevel, + ); + +bool _isMultilineString(String value) => value.trim().contains('\n'); + +String _formatMultilineString(String value, _Context ctx) => + '|${_chompModifier(value)}\n' + '${_indentMultilineString(value, _indentation(ctx))}'; + +String _chompModifier(String value) => value.endsWith('\n') ? '' : '-'; + +String _indentMultilineString(String value, String indentation) => + value.split('\n').map((s) => '$indentation$s').join('\n'); + +String _formatSingleLineString(String value, _Context ctx) => + _requiresQuotes(value) ? '"$value"' : value; + +bool _requiresQuotes(String s) => + _isNumeric(s) || _isBoolean(s) || _containsSpecialCharacters(s); + +bool _isNumeric(String s) => s.isNotEmpty && num.tryParse(s) != null; + +bool _isBoolean(String s) => _booleanValues.contains(s); + +bool _containsSpecialCharacters(String s) => + _specialCharacters.any((c) => s.contains(c)); + +const _specialCharacters = { + ': ', // Indicates mapping in YAML + '[', + ']', + '{', + '}', + '>', + '!', + '*', + '&', + '|', + '%', + ' #', // Indicates comment in YAML + '`', + '@', + ',', + '?', +}; + +const _booleanValues = { + '${true}', + '${false}', +}; diff --git a/lib/src/extensions/string_extensions.dart b/lib/src/extensions/string_extensions.dart new file mode 100644 index 0000000..3110a18 --- /dev/null +++ b/lib/src/extensions/string_extensions.dart @@ -0,0 +1,32 @@ +import 'dart:convert'; +import 'package:yaml/yaml.dart'; + +/// String validation extensions +extension StringValidationX on String? { + /// Checks a string is null or empty. + bool get isNullOrEmpty => this == null || this!.isEmpty; +} + +/// String format extensions +extension StringFormatingX on String { + /// Replaces the format item in a specified string with the string + /// representation of a corresponding object in a specified array. + String format(List values) { + var formatted = this; + for (var i = 0; i < values.length; i++) { + formatted = formatted.replaceAll('{$i}', values[i]); + } + return formatted; + } +} + +/// String convert extensions +extension StringConvertX on String? { + /// Converts a yaml string to json. + Map yamlToJson() { + if (isNullOrEmpty) { + throw YamlException('Yaml string cannot be null or empty.', null); + } + return json.decode(json.encode(loadYaml(this!))) as Map; + } +} diff --git a/lib/src/kubeconfig_util.dart b/lib/src/kubeconfig_util.dart new file mode 100644 index 0000000..b4a4275 --- /dev/null +++ b/lib/src/kubeconfig_util.dart @@ -0,0 +1,747 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:collection/collection.dart'; +import 'package:kubeconfig/src/enums/validation_code.dart'; +import 'package:kubeconfig/src/exceptions/kubeconfig_exception.dart'; +import 'package:kubeconfig/src/extensions/object_extensions.dart'; +import 'package:kubeconfig/src/extensions/string_extensions.dart'; +import 'package:kubeconfig/src/models/kubeconfig.dart'; +import 'package:kubeconfig/src/models/validation_result.dart'; + +/// {@template kubeconfig_command_runner} +/// Utility functions for kubeconfig files and objects. +/// {@endtemplate} +class KubeconfigUtil { + /// Converts a yaml to kubeconfig object. + static Kubeconfig convertYamlToObject({required String kubeconfigYaml}) { + final kubeconfigJson = kubeconfigYaml.yamlToJson(); + final kubeconfig = Kubeconfig.fromJson(kubeconfigJson); + + return kubeconfig; + } + + /// Converts a kubeconfig object to yaml. + static String convertObjectToYaml({required Kubeconfig kubeconfig}) { + final kubeconfigJson = json.encode(kubeconfig.toJson()); + final kubeconfigYaml = + (json.decode(kubeconfigJson) as Map).toYaml(); + + return kubeconfigYaml; + } + + /// Validates a kubeconfig object. + static ValidationResult validate({ + required Kubeconfig kubeconfig, + bool throwExceptions = false, + }) { + var validationResult = _checkRequiredCoreFields( + kubeconfig: kubeconfig, + throwExceptions: throwExceptions, + ); + if (validationResult.code != ValidationCode.valid) return validationResult; + + validationResult = _checkRequiredNamedFields( + kubeconfig: kubeconfig, + throwExceptions: throwExceptions, + ); + if (validationResult.code != ValidationCode.valid) return validationResult; + + validationResult = _validateContexts( + kubeconfig: kubeconfig, + throwExceptions: throwExceptions, + ); + if (validationResult.code != ValidationCode.valid) return validationResult; + + validationResult = _validateAuthInfos( + kubeconfig: kubeconfig, + throwExceptions: throwExceptions, + ); + if (validationResult.code != ValidationCode.valid) return validationResult; + + validationResult = _validateClusters( + kubeconfig: kubeconfig, + throwExceptions: throwExceptions, + ); + if (validationResult.code != ValidationCode.valid) return validationResult; + + return validationResult; + } + + static ValidationResult _checkRequiredCoreFields({ + required Kubeconfig kubeconfig, + bool throwExceptions = false, + }) { + if (kubeconfig.clusters == null) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.clustersRequired, + message: '"clusters" was not found', + ); + } + + return const ValidationResult( + code: ValidationCode.clustersRequired, + description: '"clusters" was not found', + ); + } + + if (kubeconfig.contexts == null) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.contextsRequired, + message: '"contexts" was not found', + ); + } + + return const ValidationResult( + code: ValidationCode.contextsRequired, + description: '"contexts" was not found', + ); + } + + if (kubeconfig.authInfos == null) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.usersRequired, + message: '"users" was not found', + ); + } + + return const ValidationResult( + code: ValidationCode.usersRequired, + description: '"users" was not found', + ); + } + + return const ValidationResult( + code: ValidationCode.valid, + description: 'Valid', + ); + } + + static ValidationResult _checkRequiredNamedFields({ + required Kubeconfig kubeconfig, + bool throwExceptions = false, + }) { + // Check contexts + for (final context in kubeconfig.contexts!) { + if (context.name.isNullOrEmpty) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.nameRequiredForNamedContext, + message: '"name" is required for a named context', + ); + } + + return const ValidationResult( + code: ValidationCode.nameRequiredForNamedContext, + description: '"name" is required for a named context', + ); + } + + if (context.context == null) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.contextRequiredForNamedContext, + message: '"context" is required for a named context', + ); + } + + return const ValidationResult( + code: ValidationCode.contextRequiredForNamedContext, + description: '"context" is required for a named context', + ); + } + } + + // Check authInfos + for (final authInfo in kubeconfig.authInfos!) { + if (authInfo.name.isNullOrEmpty) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.nameRequiredForNamedUser, + message: '"name" is required for a named user', + ); + } + + return const ValidationResult( + code: ValidationCode.nameRequiredForNamedUser, + description: '"name" is required for a named user', + ); + } + + if (authInfo.user == null) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.userRequiredForNamedUser, + message: '"user" is required for a named user', + ); + } + + return const ValidationResult( + code: ValidationCode.userRequiredForNamedUser, + description: '"user" is required for a named user', + ); + } + } + + // Check clusters + for (final cluster in kubeconfig.clusters!) { + if (cluster.name.isNullOrEmpty) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.nameRequiredForNamedCluster, + message: '"name" is required for a named cluster', + ); + } + + return const ValidationResult( + code: ValidationCode.nameRequiredForNamedCluster, + description: '"name" is required for a named cluster', + ); + } + + if (cluster.cluster == null) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.clusterRequiredForNamedCluster, + message: '"cluster" is required for a named cluster', + ); + } + + return const ValidationResult( + code: ValidationCode.clusterRequiredForNamedCluster, + description: '"cluster" is required for a named cluster', + ); + } + } + + return const ValidationResult( + code: ValidationCode.valid, + description: 'Valid', + ); + } + + static ValidationResult _validateContexts({ + required Kubeconfig kubeconfig, + bool throwExceptions = false, + }) { + const clusterRequiredError = '"cluster" is required for a context'; + const userRequiredError = '"user" is required for a context'; + const currentContextNotFoundError = 'Current context was not found'; + const duplicateError = 'No more than one context with the same name'; + const clusterNotFoundError = + 'cluster "{0}" was not found for context "{1}"'; + const userNotFoundError = 'user "{0}" was not found for context "{1}"'; + const namespaceMaxLength = 63; // DNS (RFC 1123) label's max length + const namespaceFormat = + r'^[a-z0-9]([-a-z0-9]*[a-z0-9])?$'; // DNS (RFC 1123) label's regex + const namespaceMaxLengthError = 'namespace "{0}" for context "{1}" max ' + 'length cannot be greater than 63'; + const namespaceFormatError = 'namespace "{0}" for context "{1}" must be ' + 'lower case alphanumeric characters with dash'; + + for (final context in kubeconfig.contexts!) { + // Check required fields + if (context.context!.cluster.isNullOrEmpty) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.clusterRequiredForContext, + message: clusterRequiredError, + ); + } + + return const ValidationResult( + code: ValidationCode.clusterRequiredForContext, + description: clusterRequiredError, + ); + } + + if (context.context!.authInfo.isNullOrEmpty) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.userRequiredForContext, + message: userRequiredError, + ); + } + + return const ValidationResult( + code: ValidationCode.userRequiredForContext, + description: userRequiredError, + ); + } + + // Check duplicates + if (kubeconfig.contexts!.where((x) => x.name == context.name).length > + 1) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw NamedContextDuplicateException( + message: duplicateError, + ); + } + + return const ValidationResult( + code: ValidationCode.namedContextDuplicate, + description: duplicateError, + ); + } + + // Check cluster + if (kubeconfig.clusters! + .firstWhereOrNull((x) => x.name == context.context!.cluster!) == + null) { + if (throwExceptions) { + throw ClusterNotFoundForContextException( + message: clusterNotFoundError + .format([context.context!.cluster!, context.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.clusterNotFoundForContext, + description: clusterNotFoundError + .format([context.context!.cluster!, context.name!]), + ); + } + + // Check user + if (kubeconfig.authInfos! + .firstWhereOrNull((x) => x.name == context.context!.authInfo!) == + null) { + if (throwExceptions) { + throw UserNotFoundForContextException( + message: userNotFoundError + .format([context.context!.authInfo!, context.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.userNotFoundForContext, + description: userNotFoundError + .format([context.context!.authInfo!, context.name!]), + ); + } + + // Check namespace length + if (!context.context!.namespace.isNullOrEmpty && + context.context!.namespace!.length > namespaceMaxLength) { + if (throwExceptions) { + throw NamespaceInvalidMaxLengthForContextException( + message: namespaceMaxLengthError + .format([context.context!.namespace!, context.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.namespaceInvalidMaxLengthForContext, + description: namespaceMaxLengthError + .format([context.context!.namespace!, context.name!]), + ); + } + + // Check namespace format + if (!context.context!.namespace.isNullOrEmpty && + !RegExp(namespaceFormat).hasMatch(context.context!.namespace!)) { + if (throwExceptions) { + throw NamespaceFormatNotMatchForContextException( + message: namespaceFormatError + .format([context.context!.namespace!, context.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.namespaceFormatNotMatchForContext, + description: namespaceFormatError + .format([context.context!.namespace!, context.name!]), + ); + } + } + + // Check current context + if (!kubeconfig.currentContext.isNullOrEmpty && + kubeconfig.contexts! + .firstWhereOrNull((x) => x.name == kubeconfig.currentContext) == + null) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw CurrentContextNotFoundException( + message: currentContextNotFoundError, + ); + } + + return const ValidationResult( + code: ValidationCode.currentContextNotFound, + description: currentContextNotFoundError, + ); + } + + return const ValidationResult( + code: ValidationCode.valid, + description: 'Valid', + ); + } + + static ValidationResult _validateAuthInfos({ + required Kubeconfig kubeconfig, + bool throwExceptions = false, + }) { + const duplicateError = 'No more than one user with the same name'; + const clientCertError = + 'client-cert-data and client-cert are both specified for "{0}"'; + const clientKeyError = + 'client-key-data and client-key are both specified for "{0}"'; + const clientKeySpecifiedError = 'client-key-data or client-key must be ' + 'specified for "{0}" to use the clientCert auth method'; + const clientCertFileError = 'Unable to read client-cert "{0}" for "{1}"'; + const clientKeyFileError = 'Unable to read client-key "{0}" for "{1}"'; + const authProviderAndExecError = 'authProvider cannot be provided in ' + 'combination with an exec plugin for "{0}"'; + const execCommandError = + 'command must be specified for "{0}" to use exec authentication plugin'; + const execApiVersionError = 'apiVersion must be specified for "{0}" to use ' + 'exec authentication plugin'; + const execEnvError = 'env variable name must be specified for "{0}" to ' + 'use exec authentication plugin'; + const moreThanOneAuthError = 'More than one authentication method found ' + 'for "{0}"; found [token, basicAuth], only one is allowed'; + const impersonatingError = 'Requesting uid, groups or user-extra for "{0}" ' + 'without impersonating a user'; + + for (final authInfo in kubeconfig.authInfos!) { + // Check required fields + // * No required field for now + + // Check duplicates + if (kubeconfig.authInfos!.where((x) => x.name == authInfo.name).length > + 1) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw NamedUserDuplicateException( + message: duplicateError, + ); + } + + return const ValidationResult( + code: ValidationCode.namedUserDuplicate, + description: duplicateError, + ); + } + + // Check client certificates + if (!authInfo.user!.clientCertificate.isNullOrEmpty || + !authInfo.user!.clientCertificateData.isNullOrEmpty) { + // Make sure client certificate data and file aren't both specified + if (!authInfo.user!.clientCertificate.isNullOrEmpty && + !authInfo.user!.clientCertificateData.isNullOrEmpty) { + if (throwExceptions) { + throw ClientCertErrorForUserException( + message: clientCertError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.clientCertErrorForUser, + description: clientCertError.format([authInfo.name!]), + ); + } + + // Make sure client key data and file aren't both specified + if (!authInfo.user!.clientKey.isNullOrEmpty && + !authInfo.user!.clientKeyData.isNullOrEmpty) { + if (throwExceptions) { + throw ClientKeyErrorForUserException( + message: clientKeyError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.clientKeyErrorForUser, + description: clientKeyError.format([authInfo.name!]), + ); + } + + // Make sure client key data or client key is specified + if (authInfo.user!.clientKey.isNullOrEmpty && + authInfo.user!.clientKeyData.isNullOrEmpty) { + if (throwExceptions) { + throw ClientKeyNotFoundForUserException( + message: clientKeySpecifiedError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.clientKeyNotFoundForUser, + description: clientKeySpecifiedError.format([authInfo.name!]), + ); + } + + // Check client certificate file exists + if (!authInfo.user!.clientCertificate.isNullOrEmpty && + !File(authInfo.user!.clientCertificate!).existsSync()) { + if (throwExceptions) { + throw ClientCertFileErrorForUserException( + message: clientCertFileError + .format([authInfo.user!.clientCertificate!, authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.clientCertFileErrorForUser, + description: clientCertFileError + .format([authInfo.user!.clientCertificate!, authInfo.name!]), + ); + } + + // Check client key file exists + if (!authInfo.user!.clientKey.isNullOrEmpty && + !File(authInfo.user!.clientKey!).existsSync()) { + if (throwExceptions) { + throw ClientKeyFileErrorForUserException( + message: clientKeyFileError + .format([authInfo.user!.clientKey!, authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.clientKeyFileErrorForUser, + description: clientKeyFileError + .format([authInfo.user!.clientKey!, authInfo.name!]), + ); + } + } + + // Make sure authProvider and exec aren't both specified + if (authInfo.user!.authProvider != null && authInfo.user!.exec != null) { + if (throwExceptions) { + throw AuthProviderAndExecErrorForUserException( + message: authProviderAndExecError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.authProviderAndExecErrorForUser, + description: authProviderAndExecError.format([authInfo.name!]), + ); + } + + // Validate exec + if (authInfo.user!.exec != null) { + // Make sure exec command is specified + if (authInfo.user!.exec!.command.isNullOrEmpty) { + if (throwExceptions) { + throw ExecCommandNotFoundForUserException( + message: execCommandError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.execCommandNotFoundForUser, + description: execCommandError.format([authInfo.name!]), + ); + } + + // Make sure exec apiVersion is specified + if (authInfo.user!.exec!.apiVersion.isNullOrEmpty) { + if (throwExceptions) { + throw ExecApiVersionNotFoundForUserException( + message: execApiVersionError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.execApiVersionNotFoundForUser, + description: execApiVersionError.format([authInfo.name!]), + ); + } + + // Make sure exec env name is specified + if (authInfo.user!.exec!.env != null && + authInfo.user!.exec!.env!.isNotEmpty) { + for (final env in authInfo.user!.exec!.env!) { + if (env.name.isNullOrEmpty) { + if (throwExceptions) { + throw ExecEnvNameNotFoundForUserException( + message: execEnvError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.execEnvNameNotFoundForUser, + description: execEnvError.format([authInfo.name!]), + ); + } + } + } + } + + // Check multiple auth methods + if (!authInfo.user!.token.isNullOrEmpty && + (!authInfo.user!.username.isNullOrEmpty || + !authInfo.user!.password.isNullOrEmpty)) { + if (throwExceptions) { + throw MoreThanOneAuthFoundForUserException( + message: moreThanOneAuthError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.moreThanOneAuthFoundForUser, + description: moreThanOneAuthError.format([authInfo.name!]), + ); + } + + // Make sure impersonate is specified + if (authInfo.user!.impersonate.isNullOrEmpty && + (!authInfo.user!.impersonateUID.isNullOrEmpty || + authInfo.user!.impersonateGroups != null || + authInfo.user!.impersonateUserExtra != null)) { + if (throwExceptions) { + throw ImpersonatingErrorForUserException( + message: impersonatingError.format([authInfo.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.impersonatingErrorForUser, + description: impersonatingError.format([authInfo.name!]), + ); + } + } + + return const ValidationResult( + code: ValidationCode.valid, + description: 'Valid', + ); + } + + static ValidationResult _validateClusters({ + required Kubeconfig kubeconfig, + bool throwExceptions = false, + }) { + const serverRequiredError = '"server" is required for a cluster'; + const duplicateError = 'No more than one cluster with the same name'; + const certificateAuthorityError = 'certificate-authority-data and ' + 'certificate-authority are both specified for "{0}"'; + const certificateAuthorityFileError = + 'Unable to read certificate-authority "{0}" for "{1}"'; + const proxyUrlError = 'Invalid proxy-url for "{0}"'; + const proxyUrlSchemeError = 'Unsupported proxy-url scheme "{0}", must be ' + 'http, https, or socks5 for "{1}"'; + + for (final cluster in kubeconfig.clusters!) { + // Check required fields + if (cluster.cluster!.server.isNullOrEmpty) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw RequiredException( + code: ValidationCode.serverRequiredForCluster, + message: serverRequiredError, + ); + } + + return const ValidationResult( + code: ValidationCode.serverRequiredForCluster, + description: serverRequiredError, + ); + } + + // Check duplicates + if (kubeconfig.clusters!.where((x) => x.name == cluster.name).length > + 1) { + if (throwExceptions) { + // ignore: prefer_const_constructors + throw NamedClusterDuplicateException( + message: duplicateError, + ); + } + + return const ValidationResult( + code: ValidationCode.namedClusterDuplicate, + description: duplicateError, + ); + } + + // Make sure CA data and file aren't both specified + if (!cluster.cluster!.certificateAuthority.isNullOrEmpty && + !cluster.cluster!.certificateAuthorityData.isNullOrEmpty) { + if (throwExceptions) { + throw CertificateAuthorityErrorForClusterException( + message: certificateAuthorityError.format([cluster.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.certificateAuthorityErrorForCluster, + description: certificateAuthorityError.format([cluster.name!]), + ); + } + + // Check CA file exists + if (!cluster.cluster!.certificateAuthority.isNullOrEmpty && + !File(cluster.cluster!.certificateAuthority!).existsSync()) { + if (throwExceptions) { + throw CertificateAuthorityFileErrorForClusterException( + message: certificateAuthorityFileError.format( + [cluster.cluster!.certificateAuthority!, cluster.name!], + ), + ); + } + + return ValidationResult( + code: ValidationCode.certificateAuthorityFileErrorForCluster, + description: certificateAuthorityFileError + .format([cluster.cluster!.certificateAuthority!, cluster.name!]), + ); + } + + // Check proxy url + if (!cluster.cluster!.proxyURL.isNullOrEmpty) { + final proxyUri = Uri.tryParse(cluster.cluster!.proxyURL!); + + if (proxyUri == null) { + if (throwExceptions) { + throw ProxyUrlInvalidForClusterException( + message: proxyUrlError.format([cluster.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.proxyUrlInvalidForCluster, + description: proxyUrlError.format([cluster.name!]), + ); + } else if (!['http', 'https', 'socks5'].contains(proxyUri.scheme)) { + if (throwExceptions) { + throw ProxyUrlInvalidSchemeForClusterException( + message: + proxyUrlSchemeError.format([proxyUri.scheme, cluster.name!]), + ); + } + + return ValidationResult( + code: ValidationCode.proxyUrlInvalidSchemeForCluster, + description: + proxyUrlSchemeError.format([proxyUri.scheme, cluster.name!]), + ); + } + } + } + + return const ValidationResult( + code: ValidationCode.valid, + description: 'Valid', + ); + } +} diff --git a/lib/src/models/auth_info.dart b/lib/src/models/auth_info.dart new file mode 100644 index 0000000..58a6705 --- /dev/null +++ b/lib/src/models/auth_info.dart @@ -0,0 +1,128 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:kubeconfig/src/models/auth_provider_config.dart'; +import 'package:kubeconfig/src/models/exec.dart'; +import 'package:meta/meta.dart'; + +part 'auth_info.g.dart'; + +/// {@template auth_info} +/// AuthInfo contains information that describes identity information. +/// This is use to tell the kubernetes cluster who you are. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class AuthInfo extends Equatable { + /// {@macro auth_info} + const AuthInfo({ + this.authProvider, + this.clientCertificate, + this.clientCertificateData, + this.clientKey, + this.clientKeyData, + this.exec, + this.impersonate, + this.impersonateUID, + this.impersonateGroups, + this.impersonateUserExtra, + this.password, + this.token, + this.tokenFile, + this.username, + }); + + /// Creates a new instance from json. + factory AuthInfo.fromJson(Map json) => + _$AuthInfoFromJson(json); + + /// Converts to json. + Map toJson() => _$AuthInfoToJson(this); + + /// AuthProvider specifies a custom authentication plugin for the kubernetes + /// cluster. + @JsonKey(name: 'auth-provider') + final AuthProviderConfig? authProvider; + + /// ClientCertificate is the path to a client cert file for TLS. + @JsonKey(name: 'client-certificate') + final String? clientCertificate; + + /// ClientCertificateData contains PEM-encoded data from a client cert file + /// for TLS. Overrides ClientCertificate + @JsonKey(name: 'client-certificate-data') + final String? clientCertificateData; + + /// ClientKey is the path to a client key file for TLS. + @JsonKey(name: 'client-key') + final String? clientKey; + + /// ClientKeyData contains PEM-encoded data from a client key file for TLS. + /// Overrides ClientKey + @JsonKey(name: 'client-key-data') + final String? clientKeyData; + + /// Exec specifies a custom exec-based authentication plugin for the + /// kubernetes cluster. + @JsonKey(name: 'exec') + final Exec? exec; + + /// Impersonate is the username to act-as. + @JsonKey(name: 'as') + final String? impersonate; + + /// ImpersonateGroups is the groups to impersonate. + @JsonKey(name: 'as-groups') + final List? impersonateGroups; + + /// ImpersonateUID is the uid to impersonate. + @JsonKey(name: 'as-uid') + final String? impersonateUID; + + /// ImpersonateUserExtra contains additional information for impersonated + /// user. + @JsonKey(name: 'as-user-extra') + final Map>? impersonateUserExtra; + + /// Password is the password for basic authentication to the kubernetes + /// cluster. + @JsonKey(name: 'password') + final String? password; + + /// Token is the bearer token for authentication to the kubernetes cluster. + @JsonKey(name: 'token') + final String? token; + + /// TokenFile is a pointer to a file that contains a bearer token + /// (as described above). + /// If both Token and TokenFile are present, Token takes precedence. + @JsonKey(name: 'tokenFile') + final String? tokenFile; + + /// Username is the username for basic authentication to the kubernetes + /// cluster. + @JsonKey(name: 'username') + final String? username; + + @override + List get props => [ + authProvider, + clientCertificate, + clientCertificateData, + clientKey, + clientKeyData, + exec, + impersonate, + impersonateGroups, + impersonateUID, + impersonateUserExtra, + password, + token, + tokenFile, + username, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/auth_info.g.dart b/lib/src/models/auth_info.g.dart new file mode 100644 index 0000000..ff121fd --- /dev/null +++ b/lib/src/models/auth_info.g.dart @@ -0,0 +1,267 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'auth_info.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$AuthInfoCWProxy { + AuthInfo authProvider(AuthProviderConfig? authProvider); + + AuthInfo clientCertificate(String? clientCertificate); + + AuthInfo clientCertificateData(String? clientCertificateData); + + AuthInfo clientKey(String? clientKey); + + AuthInfo clientKeyData(String? clientKeyData); + + AuthInfo exec(Exec? exec); + + AuthInfo impersonate(String? impersonate); + + AuthInfo impersonateUID(String? impersonateUID); + + AuthInfo impersonateGroups(List? impersonateGroups); + + AuthInfo impersonateUserExtra( + Map>? impersonateUserExtra); + + AuthInfo password(String? password); + + AuthInfo token(String? token); + + AuthInfo tokenFile(String? tokenFile); + + AuthInfo username(String? username); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `AuthInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// AuthInfo(...).copyWith(id: 12, name: "My name") + /// ```` + AuthInfo call({ + AuthProviderConfig? authProvider, + String? clientCertificate, + String? clientCertificateData, + String? clientKey, + String? clientKeyData, + Exec? exec, + String? impersonate, + String? impersonateUID, + List? impersonateGroups, + Map>? impersonateUserExtra, + String? password, + String? token, + String? tokenFile, + String? username, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfAuthInfo.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfAuthInfo.copyWith.fieldName(...)` +class _$AuthInfoCWProxyImpl implements _$AuthInfoCWProxy { + const _$AuthInfoCWProxyImpl(this._value); + + final AuthInfo _value; + + @override + AuthInfo authProvider(AuthProviderConfig? authProvider) => + this(authProvider: authProvider); + + @override + AuthInfo clientCertificate(String? clientCertificate) => + this(clientCertificate: clientCertificate); + + @override + AuthInfo clientCertificateData(String? clientCertificateData) => + this(clientCertificateData: clientCertificateData); + + @override + AuthInfo clientKey(String? clientKey) => this(clientKey: clientKey); + + @override + AuthInfo clientKeyData(String? clientKeyData) => + this(clientKeyData: clientKeyData); + + @override + AuthInfo exec(Exec? exec) => this(exec: exec); + + @override + AuthInfo impersonate(String? impersonate) => this(impersonate: impersonate); + + @override + AuthInfo impersonateUID(String? impersonateUID) => + this(impersonateUID: impersonateUID); + + @override + AuthInfo impersonateGroups(List? impersonateGroups) => + this(impersonateGroups: impersonateGroups); + + @override + AuthInfo impersonateUserExtra( + Map>? impersonateUserExtra) => + this(impersonateUserExtra: impersonateUserExtra); + + @override + AuthInfo password(String? password) => this(password: password); + + @override + AuthInfo token(String? token) => this(token: token); + + @override + AuthInfo tokenFile(String? tokenFile) => this(tokenFile: tokenFile); + + @override + AuthInfo username(String? username) => this(username: username); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `AuthInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// AuthInfo(...).copyWith(id: 12, name: "My name") + /// ```` + AuthInfo call({ + Object? authProvider = const $CopyWithPlaceholder(), + Object? clientCertificate = const $CopyWithPlaceholder(), + Object? clientCertificateData = const $CopyWithPlaceholder(), + Object? clientKey = const $CopyWithPlaceholder(), + Object? clientKeyData = const $CopyWithPlaceholder(), + Object? exec = const $CopyWithPlaceholder(), + Object? impersonate = const $CopyWithPlaceholder(), + Object? impersonateUID = const $CopyWithPlaceholder(), + Object? impersonateGroups = const $CopyWithPlaceholder(), + Object? impersonateUserExtra = const $CopyWithPlaceholder(), + Object? password = const $CopyWithPlaceholder(), + Object? token = const $CopyWithPlaceholder(), + Object? tokenFile = const $CopyWithPlaceholder(), + Object? username = const $CopyWithPlaceholder(), + }) { + return AuthInfo( + authProvider: authProvider == const $CopyWithPlaceholder() + ? _value.authProvider + // ignore: cast_nullable_to_non_nullable + : authProvider as AuthProviderConfig?, + clientCertificate: clientCertificate == const $CopyWithPlaceholder() + ? _value.clientCertificate + // ignore: cast_nullable_to_non_nullable + : clientCertificate as String?, + clientCertificateData: + clientCertificateData == const $CopyWithPlaceholder() + ? _value.clientCertificateData + // ignore: cast_nullable_to_non_nullable + : clientCertificateData as String?, + clientKey: clientKey == const $CopyWithPlaceholder() + ? _value.clientKey + // ignore: cast_nullable_to_non_nullable + : clientKey as String?, + clientKeyData: clientKeyData == const $CopyWithPlaceholder() + ? _value.clientKeyData + // ignore: cast_nullable_to_non_nullable + : clientKeyData as String?, + exec: exec == const $CopyWithPlaceholder() + ? _value.exec + // ignore: cast_nullable_to_non_nullable + : exec as Exec?, + impersonate: impersonate == const $CopyWithPlaceholder() + ? _value.impersonate + // ignore: cast_nullable_to_non_nullable + : impersonate as String?, + impersonateUID: impersonateUID == const $CopyWithPlaceholder() + ? _value.impersonateUID + // ignore: cast_nullable_to_non_nullable + : impersonateUID as String?, + impersonateGroups: impersonateGroups == const $CopyWithPlaceholder() + ? _value.impersonateGroups + // ignore: cast_nullable_to_non_nullable + : impersonateGroups as List?, + impersonateUserExtra: impersonateUserExtra == const $CopyWithPlaceholder() + ? _value.impersonateUserExtra + // ignore: cast_nullable_to_non_nullable + : impersonateUserExtra as Map>?, + password: password == const $CopyWithPlaceholder() + ? _value.password + // ignore: cast_nullable_to_non_nullable + : password as String?, + token: token == const $CopyWithPlaceholder() + ? _value.token + // ignore: cast_nullable_to_non_nullable + : token as String?, + tokenFile: tokenFile == const $CopyWithPlaceholder() + ? _value.tokenFile + // ignore: cast_nullable_to_non_nullable + : tokenFile as String?, + username: username == const $CopyWithPlaceholder() + ? _value.username + // ignore: cast_nullable_to_non_nullable + : username as String?, + ); + } +} + +extension $AuthInfoCopyWith on AuthInfo { + /// Returns a callable class that can be used as follows: `instanceOfAuthInfo.copyWith(...)` or like so:`instanceOfAuthInfo.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$AuthInfoCWProxy get copyWith => _$AuthInfoCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AuthInfo _$AuthInfoFromJson(Map json) => AuthInfo( + authProvider: json['auth-provider'] == null + ? null + : AuthProviderConfig.fromJson( + json['auth-provider'] as Map), + clientCertificate: json['client-certificate'] as String?, + clientCertificateData: json['client-certificate-data'] as String?, + clientKey: json['client-key'] as String?, + clientKeyData: json['client-key-data'] as String?, + exec: json['exec'] == null + ? null + : Exec.fromJson(json['exec'] as Map), + impersonate: json['as'] as String?, + impersonateUID: json['as-uid'] as String?, + impersonateGroups: (json['as-groups'] as List?) + ?.map((e) => e as String) + .toList(), + impersonateUserExtra: + (json['as-user-extra'] as Map?)?.map( + (k, e) => + MapEntry(k, (e as List).map((e) => e as String).toList()), + ), + password: json['password'] as String?, + token: json['token'] as String?, + tokenFile: json['tokenFile'] as String?, + username: json['username'] as String?, + ); + +Map _$AuthInfoToJson(AuthInfo instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('auth-provider', instance.authProvider); + writeNotNull('client-certificate', instance.clientCertificate); + writeNotNull('client-certificate-data', instance.clientCertificateData); + writeNotNull('client-key', instance.clientKey); + writeNotNull('client-key-data', instance.clientKeyData); + writeNotNull('exec', instance.exec); + writeNotNull('as', instance.impersonate); + writeNotNull('as-groups', instance.impersonateGroups); + writeNotNull('as-uid', instance.impersonateUID); + writeNotNull('as-user-extra', instance.impersonateUserExtra); + writeNotNull('password', instance.password); + writeNotNull('token', instance.token); + writeNotNull('tokenFile', instance.tokenFile); + writeNotNull('username', instance.username); + return val; +} diff --git a/lib/src/models/auth_provider_config.dart b/lib/src/models/auth_provider_config.dart new file mode 100644 index 0000000..92f3d37 --- /dev/null +++ b/lib/src/models/auth_provider_config.dart @@ -0,0 +1,44 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:meta/meta.dart'; + +part 'auth_provider_config.g.dart'; + +/// {@template auth_provider_config} +/// AuthProviderConfig holds the configuration for a specified auth provider. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class AuthProviderConfig extends Equatable { + /// {@macro auth_provider_config} + const AuthProviderConfig({ + required this.name, + required this.config, + }); + + /// Creates a new instance from json. + factory AuthProviderConfig.fromJson(Map json) => + _$AuthProviderConfigFromJson(json); + + /// Converts to json. + Map toJson() => _$AuthProviderConfigToJson(this); + + /// Name + @JsonKey(name: 'name') + final String? name; + + /// Config + @JsonKey(name: 'config') + final Map? config; + + @override + List get props => [ + name, + config, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/auth_provider_config.g.dart b/lib/src/models/auth_provider_config.g.dart new file mode 100644 index 0000000..a607790 --- /dev/null +++ b/lib/src/models/auth_provider_config.g.dart @@ -0,0 +1,95 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'auth_provider_config.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$AuthProviderConfigCWProxy { + AuthProviderConfig name(String? name); + + AuthProviderConfig config(Map? config); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `AuthProviderConfig(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// AuthProviderConfig(...).copyWith(id: 12, name: "My name") + /// ```` + AuthProviderConfig call({ + String? name, + Map? config, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfAuthProviderConfig.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfAuthProviderConfig.copyWith.fieldName(...)` +class _$AuthProviderConfigCWProxyImpl implements _$AuthProviderConfigCWProxy { + const _$AuthProviderConfigCWProxyImpl(this._value); + + final AuthProviderConfig _value; + + @override + AuthProviderConfig name(String? name) => this(name: name); + + @override + AuthProviderConfig config(Map? config) => + this(config: config); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `AuthProviderConfig(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// AuthProviderConfig(...).copyWith(id: 12, name: "My name") + /// ```` + AuthProviderConfig call({ + Object? name = const $CopyWithPlaceholder(), + Object? config = const $CopyWithPlaceholder(), + }) { + return AuthProviderConfig( + name: name == const $CopyWithPlaceholder() + ? _value.name + // ignore: cast_nullable_to_non_nullable + : name as String?, + config: config == const $CopyWithPlaceholder() + ? _value.config + // ignore: cast_nullable_to_non_nullable + : config as Map?, + ); + } +} + +extension $AuthProviderConfigCopyWith on AuthProviderConfig { + /// Returns a callable class that can be used as follows: `instanceOfAuthProviderConfig.copyWith(...)` or like so:`instanceOfAuthProviderConfig.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$AuthProviderConfigCWProxy get copyWith => + _$AuthProviderConfigCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AuthProviderConfig _$AuthProviderConfigFromJson(Map json) => + AuthProviderConfig( + name: json['name'] as String?, + config: (json['config'] as Map?)?.map( + (k, e) => MapEntry(k, e as String), + ), + ); + +Map _$AuthProviderConfigToJson(AuthProviderConfig instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('name', instance.name); + writeNotNull('config', instance.config); + return val; +} diff --git a/lib/src/models/cluster.dart b/lib/src/models/cluster.dart new file mode 100644 index 0000000..71faeaf --- /dev/null +++ b/lib/src/models/cluster.dart @@ -0,0 +1,91 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:meta/meta.dart'; + +part 'cluster.g.dart'; + +/// {@template cluster} +/// Cluster contains information about how to communicate with a kubernetes +/// cluster. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class Cluster extends Equatable { + /// {@macro cluster} + const Cluster({ + required this.server, + required this.insecureSkipTlsVerify, + this.certificateAuthority, + this.certificateAuthorityData, + this.disableCompression, + this.proxyURL, + this.tlsServerName, + }); + + /// Creates a new instance from json. + factory Cluster.fromJson(Map json) => + _$ClusterFromJson(json); + + /// Converts to json. + Map toJson() => _$ClusterToJson(this); + + /// CertificateAuthority is the path to a cert file for the certificate + /// authority. + @JsonKey(name: 'certificate-authority') + final String? certificateAuthority; + + /// CertificateAuthorityData contains PEM-encoded certificate authority + /// certificates. Overrides CertificateAuthority + @JsonKey(name: 'certificate-authority-data') + final String? certificateAuthorityData; + + /// DisableCompression allows client to opt-out of response compression + /// for all requests to the server. This is useful to speed up requests + /// (specifically lists) when client-server network bandwidth is ample, + /// by saving time on compression (server-side) and decompression + /// (client-side): https://github.com/kubernetes/kubernetes/issues/112296. + @JsonKey(name: 'disable-compression') + final bool? disableCompression; + + /// InsecureSkipTLSVerify skips the validity check for the server's + /// certificate. This will make your HTTPS connections insecure. + @JsonKey(name: 'insecure-skip-tls-verify') + final bool? insecureSkipTlsVerify; + + /// ProxyURL is the URL to the proxy to be used for all requests made by this + /// client. URLs with "http", "https", and "socks5" schemes are supported. If + /// this configuration is not provided or the empty string, the client + /// attempts to construct a proxy configuration from http_proxy and + /// https_proxy environment variables. If these environment variables are not + /// set, the client does not attempt to proxy requests. + /// + /// socks5 proxying does not currently support spdy streaming endpoints (exec, + /// attach, port forward). + @JsonKey(name: 'proxy-url') + final String? proxyURL; + + /// Server is the address of the kubernetes cluster (https://hostname:port). + @JsonKey(name: 'server') + final String? server; + + /// TLSServerName is used to check server certificate. If TLSServerName is + /// empty, the hostname used to contact the server is used. + @JsonKey(name: 'tls-server-name') + final String? tlsServerName; + + @override + List get props => [ + certificateAuthority, + certificateAuthorityData, + disableCompression, + insecureSkipTlsVerify, + proxyURL, + server, + tlsServerName, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/cluster.g.dart b/lib/src/models/cluster.g.dart new file mode 100644 index 0000000..35ebfd3 --- /dev/null +++ b/lib/src/models/cluster.g.dart @@ -0,0 +1,162 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'cluster.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$ClusterCWProxy { + Cluster server(String? server); + + Cluster insecureSkipTlsVerify(bool? insecureSkipTlsVerify); + + Cluster certificateAuthority(String? certificateAuthority); + + Cluster certificateAuthorityData(String? certificateAuthorityData); + + Cluster disableCompression(bool? disableCompression); + + Cluster proxyURL(String? proxyURL); + + Cluster tlsServerName(String? tlsServerName); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Cluster(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Cluster(...).copyWith(id: 12, name: "My name") + /// ```` + Cluster call({ + String? server, + bool? insecureSkipTlsVerify, + String? certificateAuthority, + String? certificateAuthorityData, + bool? disableCompression, + String? proxyURL, + String? tlsServerName, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfCluster.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfCluster.copyWith.fieldName(...)` +class _$ClusterCWProxyImpl implements _$ClusterCWProxy { + const _$ClusterCWProxyImpl(this._value); + + final Cluster _value; + + @override + Cluster server(String? server) => this(server: server); + + @override + Cluster insecureSkipTlsVerify(bool? insecureSkipTlsVerify) => + this(insecureSkipTlsVerify: insecureSkipTlsVerify); + + @override + Cluster certificateAuthority(String? certificateAuthority) => + this(certificateAuthority: certificateAuthority); + + @override + Cluster certificateAuthorityData(String? certificateAuthorityData) => + this(certificateAuthorityData: certificateAuthorityData); + + @override + Cluster disableCompression(bool? disableCompression) => + this(disableCompression: disableCompression); + + @override + Cluster proxyURL(String? proxyURL) => this(proxyURL: proxyURL); + + @override + Cluster tlsServerName(String? tlsServerName) => + this(tlsServerName: tlsServerName); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Cluster(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Cluster(...).copyWith(id: 12, name: "My name") + /// ```` + Cluster call({ + Object? server = const $CopyWithPlaceholder(), + Object? insecureSkipTlsVerify = const $CopyWithPlaceholder(), + Object? certificateAuthority = const $CopyWithPlaceholder(), + Object? certificateAuthorityData = const $CopyWithPlaceholder(), + Object? disableCompression = const $CopyWithPlaceholder(), + Object? proxyURL = const $CopyWithPlaceholder(), + Object? tlsServerName = const $CopyWithPlaceholder(), + }) { + return Cluster( + server: server == const $CopyWithPlaceholder() + ? _value.server + // ignore: cast_nullable_to_non_nullable + : server as String?, + insecureSkipTlsVerify: + insecureSkipTlsVerify == const $CopyWithPlaceholder() + ? _value.insecureSkipTlsVerify + // ignore: cast_nullable_to_non_nullable + : insecureSkipTlsVerify as bool?, + certificateAuthority: certificateAuthority == const $CopyWithPlaceholder() + ? _value.certificateAuthority + // ignore: cast_nullable_to_non_nullable + : certificateAuthority as String?, + certificateAuthorityData: + certificateAuthorityData == const $CopyWithPlaceholder() + ? _value.certificateAuthorityData + // ignore: cast_nullable_to_non_nullable + : certificateAuthorityData as String?, + disableCompression: disableCompression == const $CopyWithPlaceholder() + ? _value.disableCompression + // ignore: cast_nullable_to_non_nullable + : disableCompression as bool?, + proxyURL: proxyURL == const $CopyWithPlaceholder() + ? _value.proxyURL + // ignore: cast_nullable_to_non_nullable + : proxyURL as String?, + tlsServerName: tlsServerName == const $CopyWithPlaceholder() + ? _value.tlsServerName + // ignore: cast_nullable_to_non_nullable + : tlsServerName as String?, + ); + } +} + +extension $ClusterCopyWith on Cluster { + /// Returns a callable class that can be used as follows: `instanceOfCluster.copyWith(...)` or like so:`instanceOfCluster.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$ClusterCWProxy get copyWith => _$ClusterCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Cluster _$ClusterFromJson(Map json) => Cluster( + server: json['server'] as String?, + insecureSkipTlsVerify: json['insecure-skip-tls-verify'] as bool?, + certificateAuthority: json['certificate-authority'] as String?, + certificateAuthorityData: json['certificate-authority-data'] as String?, + disableCompression: json['disable-compression'] as bool?, + proxyURL: json['proxy-url'] as String?, + tlsServerName: json['tls-server-name'] as String?, + ); + +Map _$ClusterToJson(Cluster instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('certificate-authority', instance.certificateAuthority); + writeNotNull('certificate-authority-data', instance.certificateAuthorityData); + writeNotNull('disable-compression', instance.disableCompression); + writeNotNull('insecure-skip-tls-verify', instance.insecureSkipTlsVerify); + writeNotNull('proxy-url', instance.proxyURL); + writeNotNull('server', instance.server); + writeNotNull('tls-server-name', instance.tlsServerName); + return val; +} diff --git a/lib/src/models/context.dart b/lib/src/models/context.dart new file mode 100644 index 0000000..4004c2c --- /dev/null +++ b/lib/src/models/context.dart @@ -0,0 +1,52 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:meta/meta.dart'; + +part 'context.g.dart'; + +/// {@template context} +/// Context is a tuple of references to a cluster (how do I communicate with +/// a kubernetes cluster), a user (how do I identify myself), and a namespace +/// (what subset of resources do I want to work with). +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class Context extends Equatable { + /// {@macro context} + const Context({ + required this.cluster, + required this.authInfo, + this.namespace, + }); + + /// Creates a new instance from json. + factory Context.fromJson(Map json) => + _$ContextFromJson(json); + + /// Converts to json. + Map toJson() => _$ContextToJson(this); + + /// Cluster is the name of the cluster for this context + @JsonKey(name: 'cluster') + final String? cluster; + + /// Namespace is the default namespace to use on unspecified requests + @JsonKey(name: 'namespace') + final String? namespace; + + /// AuthInfo is the name of the user for this context + @JsonKey(name: 'user') + final String? authInfo; + + @override + List get props => [ + cluster, + authInfo, + namespace, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/context.g.dart b/lib/src/models/context.g.dart new file mode 100644 index 0000000..d1fed2f --- /dev/null +++ b/lib/src/models/context.g.dart @@ -0,0 +1,103 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'context.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$ContextCWProxy { + Context cluster(String? cluster); + + Context authInfo(String? authInfo); + + Context namespace(String? namespace); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Context(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Context(...).copyWith(id: 12, name: "My name") + /// ```` + Context call({ + String? cluster, + String? authInfo, + String? namespace, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfContext.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfContext.copyWith.fieldName(...)` +class _$ContextCWProxyImpl implements _$ContextCWProxy { + const _$ContextCWProxyImpl(this._value); + + final Context _value; + + @override + Context cluster(String? cluster) => this(cluster: cluster); + + @override + Context authInfo(String? authInfo) => this(authInfo: authInfo); + + @override + Context namespace(String? namespace) => this(namespace: namespace); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Context(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Context(...).copyWith(id: 12, name: "My name") + /// ```` + Context call({ + Object? cluster = const $CopyWithPlaceholder(), + Object? authInfo = const $CopyWithPlaceholder(), + Object? namespace = const $CopyWithPlaceholder(), + }) { + return Context( + cluster: cluster == const $CopyWithPlaceholder() + ? _value.cluster + // ignore: cast_nullable_to_non_nullable + : cluster as String?, + authInfo: authInfo == const $CopyWithPlaceholder() + ? _value.authInfo + // ignore: cast_nullable_to_non_nullable + : authInfo as String?, + namespace: namespace == const $CopyWithPlaceholder() + ? _value.namespace + // ignore: cast_nullable_to_non_nullable + : namespace as String?, + ); + } +} + +extension $ContextCopyWith on Context { + /// Returns a callable class that can be used as follows: `instanceOfContext.copyWith(...)` or like so:`instanceOfContext.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$ContextCWProxy get copyWith => _$ContextCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Context _$ContextFromJson(Map json) => Context( + cluster: json['cluster'] as String?, + authInfo: json['user'] as String?, + namespace: json['namespace'] as String?, + ); + +Map _$ContextToJson(Context instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('cluster', instance.cluster); + writeNotNull('namespace', instance.namespace); + writeNotNull('user', instance.authInfo); + return val; +} diff --git a/lib/src/models/exec.dart b/lib/src/models/exec.dart new file mode 100644 index 0000000..e9c3f75 --- /dev/null +++ b/lib/src/models/exec.dart @@ -0,0 +1,101 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:kubeconfig/src/enums/interactive_mode.dart'; +import 'package:kubeconfig/src/models/exec_env.dart'; +import 'package:meta/meta.dart'; + +part 'exec.g.dart'; + +/// {@template exec} +/// ExecConfig specifies a command to provide client credentials. The command +/// is exec'd and outputs structured stdout holding +/// credentials. +/// +/// See the client.authentication.k8s.io API group for specifications of the +/// exact input and output format. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class Exec extends Equatable { + /// {@macro exec} + const Exec({ + required this.command, + required this.apiVersion, + required this.interactiveMode, + this.env, + this.args, + this.installHint, + this.provideClusterInfo, + }); + + /// Creates a new instance from json. + factory Exec.fromJson(Map json) => _$ExecFromJson(json); + + /// Converts to json. + Map toJson() => _$ExecToJson(this); + + /// Command to execute. + @JsonKey(name: 'command') + final String? command; + + /// Preferred input version of the ExecInfo. The returned ExecCredentials + /// MUST use the same encoding version as the input. + @JsonKey(name: 'apiVersion') + final String? apiVersion; + + /// Env defines additional environment variables to expose to the process. + /// These are unioned with the host's environment, as well as variables + /// kubeconfig uses to pass argument to the plugin. + @JsonKey(name: 'env') + final List? env; + + /// Arguments to pass to the command when executing it. + @JsonKey(name: 'args') + final List? args; + + /// This text is shown to the user when the executable doesn't seem to be + /// present. For example, `brew install foo-cli` might be a good InstallHint + /// for foo-cli on Mac OS systems. + @JsonKey(name: 'installHint') + final String? installHint; + + /// InteractiveMode determines this plugin's relationship with standard input. + /// Valid values are "Never" (this exec plugin never uses standard input), + /// "IfAvailable" (this exec plugin wants to use standard input if it is + /// available), or "Always" (this exec plugin requires standard input to + /// function). See ExecInteractiveMode values for more details. + /// + /// If APIVersion is client.authentication.k8s.io/v1alpha1 or + /// client.authentication.k8s.io/v1beta1, then this field is optional and + /// defaults to "IfAvailable" when unset. Otherwise, this field is required. + @JsonKey( + name: 'interactiveMode', + unknownEnumValue: JsonKey.nullForUndefinedEnumValue, + defaultValue: InteractiveMode.IfAvailable, + ) + final InteractiveMode? interactiveMode; + + /// ProvideClusterInfo determines whether or not to provide cluster + /// information, which could potentially contain very large CA data, to this + /// exec plugin as a part of the KUBERNETES_EXEC_INFO environment variable. + /// By default, it is set to false. Package k8s.io/client-go/tools/auth/exec + /// provides helper methods for reading this environment variable. + @JsonKey(name: 'provideClusterInfo') + final bool? provideClusterInfo; + + @override + List get props => [ + command, + apiVersion, + interactiveMode, + env, + args, + installHint, + provideClusterInfo, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/exec.g.dart b/lib/src/models/exec.g.dart new file mode 100644 index 0000000..593db60 --- /dev/null +++ b/lib/src/models/exec.g.dart @@ -0,0 +1,169 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'exec.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$ExecCWProxy { + Exec command(String? command); + + Exec apiVersion(String? apiVersion); + + Exec interactiveMode(InteractiveMode? interactiveMode); + + Exec env(List? env); + + Exec args(List? args); + + Exec installHint(String? installHint); + + Exec provideClusterInfo(bool? provideClusterInfo); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Exec(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Exec(...).copyWith(id: 12, name: "My name") + /// ```` + Exec call({ + String? command, + String? apiVersion, + InteractiveMode? interactiveMode, + List? env, + List? args, + String? installHint, + bool? provideClusterInfo, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfExec.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfExec.copyWith.fieldName(...)` +class _$ExecCWProxyImpl implements _$ExecCWProxy { + const _$ExecCWProxyImpl(this._value); + + final Exec _value; + + @override + Exec command(String? command) => this(command: command); + + @override + Exec apiVersion(String? apiVersion) => this(apiVersion: apiVersion); + + @override + Exec interactiveMode(InteractiveMode? interactiveMode) => + this(interactiveMode: interactiveMode); + + @override + Exec env(List? env) => this(env: env); + + @override + Exec args(List? args) => this(args: args); + + @override + Exec installHint(String? installHint) => this(installHint: installHint); + + @override + Exec provideClusterInfo(bool? provideClusterInfo) => + this(provideClusterInfo: provideClusterInfo); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Exec(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Exec(...).copyWith(id: 12, name: "My name") + /// ```` + Exec call({ + Object? command = const $CopyWithPlaceholder(), + Object? apiVersion = const $CopyWithPlaceholder(), + Object? interactiveMode = const $CopyWithPlaceholder(), + Object? env = const $CopyWithPlaceholder(), + Object? args = const $CopyWithPlaceholder(), + Object? installHint = const $CopyWithPlaceholder(), + Object? provideClusterInfo = const $CopyWithPlaceholder(), + }) { + return Exec( + command: command == const $CopyWithPlaceholder() + ? _value.command + // ignore: cast_nullable_to_non_nullable + : command as String?, + apiVersion: apiVersion == const $CopyWithPlaceholder() + ? _value.apiVersion + // ignore: cast_nullable_to_non_nullable + : apiVersion as String?, + interactiveMode: interactiveMode == const $CopyWithPlaceholder() + ? _value.interactiveMode + // ignore: cast_nullable_to_non_nullable + : interactiveMode as InteractiveMode?, + env: env == const $CopyWithPlaceholder() + ? _value.env + // ignore: cast_nullable_to_non_nullable + : env as List?, + args: args == const $CopyWithPlaceholder() + ? _value.args + // ignore: cast_nullable_to_non_nullable + : args as List?, + installHint: installHint == const $CopyWithPlaceholder() + ? _value.installHint + // ignore: cast_nullable_to_non_nullable + : installHint as String?, + provideClusterInfo: provideClusterInfo == const $CopyWithPlaceholder() + ? _value.provideClusterInfo + // ignore: cast_nullable_to_non_nullable + : provideClusterInfo as bool?, + ); + } +} + +extension $ExecCopyWith on Exec { + /// Returns a callable class that can be used as follows: `instanceOfExec.copyWith(...)` or like so:`instanceOfExec.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$ExecCWProxy get copyWith => _$ExecCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Exec _$ExecFromJson(Map json) => Exec( + command: json['command'] as String?, + apiVersion: json['apiVersion'] as String?, + interactiveMode: $enumDecodeNullable( + _$InteractiveModeEnumMap, json['interactiveMode'], + unknownValue: JsonKey.nullForUndefinedEnumValue) ?? + InteractiveMode.IfAvailable, + env: (json['env'] as List?) + ?.map((e) => ExecEnv.fromJson(e as Map)) + .toList(), + args: (json['args'] as List?)?.map((e) => e as String).toList(), + installHint: json['installHint'] as String?, + provideClusterInfo: json['provideClusterInfo'] as bool?, + ); + +Map _$ExecToJson(Exec instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('command', instance.command); + writeNotNull('apiVersion', instance.apiVersion); + writeNotNull('env', instance.env); + writeNotNull('args', instance.args); + writeNotNull('installHint', instance.installHint); + writeNotNull( + 'interactiveMode', _$InteractiveModeEnumMap[instance.interactiveMode]); + writeNotNull('provideClusterInfo', instance.provideClusterInfo); + return val; +} + +const _$InteractiveModeEnumMap = { + InteractiveMode.Always: 'Always', + InteractiveMode.IfAvailable: 'IfAvailable', + InteractiveMode.Never: 'Never', +}; diff --git a/lib/src/models/exec_env.dart b/lib/src/models/exec_env.dart new file mode 100644 index 0000000..c78916d --- /dev/null +++ b/lib/src/models/exec_env.dart @@ -0,0 +1,45 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:meta/meta.dart'; + +part 'exec_env.g.dart'; + +/// {@template exec_env} +/// ExecEnvVar is used for setting environment variables when executing an +/// exec-based credential plugin. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class ExecEnv extends Equatable { + /// {@macro exec_env} + const ExecEnv({ + required this.name, + required this.value, + }); + + /// Creates a new instance from json. + factory ExecEnv.fromJson(Map json) => + _$ExecEnvFromJson(json); + + /// Converts to json. + Map toJson() => _$ExecEnvToJson(this); + + /// Name + @JsonKey(name: 'name') + final String? name; + + /// Value + @JsonKey(name: 'value') + final String? value; + + @override + List get props => [ + name, + value, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/exec_env.g.dart b/lib/src/models/exec_env.g.dart new file mode 100644 index 0000000..0837319 --- /dev/null +++ b/lib/src/models/exec_env.g.dart @@ -0,0 +1,90 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'exec_env.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$ExecEnvCWProxy { + ExecEnv name(String? name); + + ExecEnv value(String? value); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `ExecEnv(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// ExecEnv(...).copyWith(id: 12, name: "My name") + /// ```` + ExecEnv call({ + String? name, + String? value, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfExecEnv.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfExecEnv.copyWith.fieldName(...)` +class _$ExecEnvCWProxyImpl implements _$ExecEnvCWProxy { + const _$ExecEnvCWProxyImpl(this._value); + + final ExecEnv _value; + + @override + ExecEnv name(String? name) => this(name: name); + + @override + ExecEnv value(String? value) => this(value: value); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `ExecEnv(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// ExecEnv(...).copyWith(id: 12, name: "My name") + /// ```` + ExecEnv call({ + Object? name = const $CopyWithPlaceholder(), + Object? value = const $CopyWithPlaceholder(), + }) { + return ExecEnv( + name: name == const $CopyWithPlaceholder() + ? _value.name + // ignore: cast_nullable_to_non_nullable + : name as String?, + value: value == const $CopyWithPlaceholder() + ? _value.value + // ignore: cast_nullable_to_non_nullable + : value as String?, + ); + } +} + +extension $ExecEnvCopyWith on ExecEnv { + /// Returns a callable class that can be used as follows: `instanceOfExecEnv.copyWith(...)` or like so:`instanceOfExecEnv.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$ExecEnvCWProxy get copyWith => _$ExecEnvCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ExecEnv _$ExecEnvFromJson(Map json) => ExecEnv( + name: json['name'] as String?, + value: json['value'] as String?, + ); + +Map _$ExecEnvToJson(ExecEnv instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('name', instance.name); + writeNotNull('value', instance.value); + return val; +} diff --git a/lib/src/models/kubeconfig.dart b/lib/src/models/kubeconfig.dart new file mode 100644 index 0000000..461b9e2 --- /dev/null +++ b/lib/src/models/kubeconfig.dart @@ -0,0 +1,158 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:kubeconfig/src/enums/validation_code.dart'; +import 'package:kubeconfig/src/kubeconfig_util.dart'; +import 'package:kubeconfig/src/models/named_auth_info.dart'; +import 'package:kubeconfig/src/models/named_cluster.dart'; +import 'package:kubeconfig/src/models/named_context.dart'; +import 'package:kubeconfig/src/models/preferences.dart'; +import 'package:kubeconfig/src/models/validation_result.dart'; +import 'package:meta/meta.dart'; + +part 'kubeconfig.g.dart'; + +/// {@template kubeconfig} +/// Kubeconfig holds the information needed to build connect to remote +/// kubernetes clusters as a given user. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class Kubeconfig extends Equatable { + /// {@macro kubeconfig} + const Kubeconfig({ + required this.clusters, + required this.contexts, + required this.authInfos, + this.apiVersion, + this.currentContext, + this.kind, + this.preferences, + }); + + /// Creates a new instance from json. + factory Kubeconfig.fromJson(Map json) => + _$KubeconfigFromJson(json); + + /// Creates a new instance from yaml. + factory Kubeconfig.fromYaml(String yaml) => + KubeconfigUtil.convertYamlToObject(kubeconfigYaml: yaml); + + /// Converts to json. + Map toJson() => _$KubeconfigToJson(this); + + /// Converts to yaml. + String toYaml() => KubeconfigUtil.convertObjectToYaml(kubeconfig: this); + + /// Validates the kubeconfig. + ValidationResult validate({bool throwExceptions = false}) { + return KubeconfigUtil.validate( + kubeconfig: this, + throwExceptions: throwExceptions, + ); + } + + /// Merges a kubeconfig into this object. + /// Returns null if kubeconfig objects (source and target) are not valid + /// when [validate] is true and [throwExceptions] is false + Kubeconfig? merge( + Kubeconfig config, { + bool validate = true, + bool throwExceptions = false, + bool preserveCurrentContext = false, + }) { + if (validate) { + final resultSource = KubeconfigUtil.validate( + kubeconfig: this, + throwExceptions: throwExceptions, + ); + + if (resultSource.code != ValidationCode.valid) { + return null; + } + + final resultTarget = KubeconfigUtil.validate( + kubeconfig: config, + throwExceptions: throwExceptions, + ); + + if (resultTarget.code != ValidationCode.valid) { + return null; + } + } + + Kubeconfig kubeconfig; + + if (!preserveCurrentContext) { + kubeconfig = copyWith(currentContext: config.currentContext); + } else { + kubeconfig = copyWith(); + } + + final clusterList = clusters!; + final authInfoList = authInfos!; + final contextList = contexts!; + + for (final cluster in config.clusters!) { + clusterList.add(cluster); + } + + kubeconfig = kubeconfig.copyWith(clusters: clusterList); + + for (final authInfo in config.authInfos!) { + authInfoList.add(authInfo); + } + + kubeconfig = kubeconfig.copyWith(authInfos: authInfoList); + + for (final context in config.contexts!) { + contextList.add(context); + } + + return kubeconfig.copyWith(contexts: contextList); + } + + /// v1 (default value) + @JsonKey(name: 'apiVersion', defaultValue: 'v1') + final String? apiVersion; + + /// Clusters is a map of referencable names to cluster configs. + @JsonKey(name: 'clusters') + final List? clusters; + + /// Contexts is a map of referencable names to context configs. + @JsonKey(name: 'contexts') + final List? contexts; + + /// CurrentContext is the name of the context that you would like to use + /// by default. + @JsonKey(name: 'current-context') + final String? currentContext; + + /// Config (default value) + @JsonKey(name: 'kind', defaultValue: 'Config') + final String? kind; + + /// Preferences holds general information to be use for cli interactions. + @JsonKey(name: 'preferences') + final Preferences? preferences; + + /// AuthInfos is a map of referencable names to user configs. + @JsonKey(name: 'users') + final List? authInfos; + + @override + List get props => [ + clusters, + contexts, + authInfos, + apiVersion, + currentContext, + kind, + preferences, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/kubeconfig.g.dart b/lib/src/models/kubeconfig.g.dart new file mode 100644 index 0000000..7232511 --- /dev/null +++ b/lib/src/models/kubeconfig.g.dart @@ -0,0 +1,166 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'kubeconfig.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$KubeconfigCWProxy { + Kubeconfig clusters(List? clusters); + + Kubeconfig contexts(List? contexts); + + Kubeconfig authInfos(List? authInfos); + + Kubeconfig apiVersion(String? apiVersion); + + Kubeconfig currentContext(String? currentContext); + + Kubeconfig kind(String? kind); + + Kubeconfig preferences(Preferences? preferences); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Kubeconfig(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Kubeconfig(...).copyWith(id: 12, name: "My name") + /// ```` + Kubeconfig call({ + List? clusters, + List? contexts, + List? authInfos, + String? apiVersion, + String? currentContext, + String? kind, + Preferences? preferences, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfKubeconfig.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfKubeconfig.copyWith.fieldName(...)` +class _$KubeconfigCWProxyImpl implements _$KubeconfigCWProxy { + const _$KubeconfigCWProxyImpl(this._value); + + final Kubeconfig _value; + + @override + Kubeconfig clusters(List? clusters) => this(clusters: clusters); + + @override + Kubeconfig contexts(List? contexts) => this(contexts: contexts); + + @override + Kubeconfig authInfos(List? authInfos) => + this(authInfos: authInfos); + + @override + Kubeconfig apiVersion(String? apiVersion) => this(apiVersion: apiVersion); + + @override + Kubeconfig currentContext(String? currentContext) => + this(currentContext: currentContext); + + @override + Kubeconfig kind(String? kind) => this(kind: kind); + + @override + Kubeconfig preferences(Preferences? preferences) => + this(preferences: preferences); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Kubeconfig(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Kubeconfig(...).copyWith(id: 12, name: "My name") + /// ```` + Kubeconfig call({ + Object? clusters = const $CopyWithPlaceholder(), + Object? contexts = const $CopyWithPlaceholder(), + Object? authInfos = const $CopyWithPlaceholder(), + Object? apiVersion = const $CopyWithPlaceholder(), + Object? currentContext = const $CopyWithPlaceholder(), + Object? kind = const $CopyWithPlaceholder(), + Object? preferences = const $CopyWithPlaceholder(), + }) { + return Kubeconfig( + clusters: clusters == const $CopyWithPlaceholder() + ? _value.clusters + // ignore: cast_nullable_to_non_nullable + : clusters as List?, + contexts: contexts == const $CopyWithPlaceholder() + ? _value.contexts + // ignore: cast_nullable_to_non_nullable + : contexts as List?, + authInfos: authInfos == const $CopyWithPlaceholder() + ? _value.authInfos + // ignore: cast_nullable_to_non_nullable + : authInfos as List?, + apiVersion: apiVersion == const $CopyWithPlaceholder() + ? _value.apiVersion + // ignore: cast_nullable_to_non_nullable + : apiVersion as String?, + currentContext: currentContext == const $CopyWithPlaceholder() + ? _value.currentContext + // ignore: cast_nullable_to_non_nullable + : currentContext as String?, + kind: kind == const $CopyWithPlaceholder() + ? _value.kind + // ignore: cast_nullable_to_non_nullable + : kind as String?, + preferences: preferences == const $CopyWithPlaceholder() + ? _value.preferences + // ignore: cast_nullable_to_non_nullable + : preferences as Preferences?, + ); + } +} + +extension $KubeconfigCopyWith on Kubeconfig { + /// Returns a callable class that can be used as follows: `instanceOfKubeconfig.copyWith(...)` or like so:`instanceOfKubeconfig.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$KubeconfigCWProxy get copyWith => _$KubeconfigCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Kubeconfig _$KubeconfigFromJson(Map json) => Kubeconfig( + clusters: (json['clusters'] as List?) + ?.map((e) => NamedCluster.fromJson(e as Map)) + .toList(), + contexts: (json['contexts'] as List?) + ?.map((e) => NamedContext.fromJson(e as Map)) + .toList(), + authInfos: (json['users'] as List?) + ?.map((e) => NamedAuthInfo.fromJson(e as Map)) + .toList(), + apiVersion: json['apiVersion'] as String? ?? 'v1', + currentContext: json['current-context'] as String?, + kind: json['kind'] as String? ?? 'Config', + preferences: json['preferences'] == null + ? null + : Preferences.fromJson(json['preferences'] as Map), + ); + +Map _$KubeconfigToJson(Kubeconfig instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('apiVersion', instance.apiVersion); + writeNotNull('clusters', instance.clusters); + writeNotNull('contexts', instance.contexts); + writeNotNull('current-context', instance.currentContext); + writeNotNull('kind', instance.kind); + writeNotNull('preferences', instance.preferences); + writeNotNull('users', instance.authInfos); + return val; +} diff --git a/lib/src/models/models.dart b/lib/src/models/models.dart new file mode 100644 index 0000000..a3ef2ed --- /dev/null +++ b/lib/src/models/models.dart @@ -0,0 +1,12 @@ +export 'auth_info.dart'; +export 'auth_provider_config.dart'; +export 'cluster.dart'; +export 'context.dart'; +export 'exec.dart'; +export 'exec_env.dart'; +export 'kubeconfig.dart'; +export 'named_auth_info.dart'; +export 'named_cluster.dart'; +export 'named_context.dart'; +export 'preferences.dart'; +export 'validation_result.dart'; diff --git a/lib/src/models/named_auth_info.dart b/lib/src/models/named_auth_info.dart new file mode 100644 index 0000000..946478d --- /dev/null +++ b/lib/src/models/named_auth_info.dart @@ -0,0 +1,45 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:kubeconfig/src/models/auth_info.dart'; +import 'package:meta/meta.dart'; + +part 'named_auth_info.g.dart'; + +/// {@template named_auth_info} +/// NamedAuthInfo relates nicknames to auth information. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class NamedAuthInfo extends Equatable { + /// {@macro named_auth_info} + const NamedAuthInfo({ + required this.name, + required this.user, + }); + + /// Creates a new instance from json. + factory NamedAuthInfo.fromJson(Map json) => + _$NamedAuthInfoFromJson(json); + + /// Converts to json. + Map toJson() => _$NamedAuthInfoToJson(this); + + /// Name is the nickname for this AuthInfo. + @JsonKey(name: 'name') + final String? name; + + /// AuthInfo holds the auth information. + @JsonKey(name: 'user') + final AuthInfo? user; + + @override + List get props => [ + name, + user, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/named_auth_info.g.dart b/lib/src/models/named_auth_info.g.dart new file mode 100644 index 0000000..b1397f3 --- /dev/null +++ b/lib/src/models/named_auth_info.g.dart @@ -0,0 +1,93 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'named_auth_info.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$NamedAuthInfoCWProxy { + NamedAuthInfo name(String? name); + + NamedAuthInfo user(AuthInfo? user); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `NamedAuthInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// NamedAuthInfo(...).copyWith(id: 12, name: "My name") + /// ```` + NamedAuthInfo call({ + String? name, + AuthInfo? user, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfNamedAuthInfo.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfNamedAuthInfo.copyWith.fieldName(...)` +class _$NamedAuthInfoCWProxyImpl implements _$NamedAuthInfoCWProxy { + const _$NamedAuthInfoCWProxyImpl(this._value); + + final NamedAuthInfo _value; + + @override + NamedAuthInfo name(String? name) => this(name: name); + + @override + NamedAuthInfo user(AuthInfo? user) => this(user: user); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `NamedAuthInfo(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// NamedAuthInfo(...).copyWith(id: 12, name: "My name") + /// ```` + NamedAuthInfo call({ + Object? name = const $CopyWithPlaceholder(), + Object? user = const $CopyWithPlaceholder(), + }) { + return NamedAuthInfo( + name: name == const $CopyWithPlaceholder() + ? _value.name + // ignore: cast_nullable_to_non_nullable + : name as String?, + user: user == const $CopyWithPlaceholder() + ? _value.user + // ignore: cast_nullable_to_non_nullable + : user as AuthInfo?, + ); + } +} + +extension $NamedAuthInfoCopyWith on NamedAuthInfo { + /// Returns a callable class that can be used as follows: `instanceOfNamedAuthInfo.copyWith(...)` or like so:`instanceOfNamedAuthInfo.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$NamedAuthInfoCWProxy get copyWith => _$NamedAuthInfoCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NamedAuthInfo _$NamedAuthInfoFromJson(Map json) => + NamedAuthInfo( + name: json['name'] as String?, + user: json['user'] == null + ? null + : AuthInfo.fromJson(json['user'] as Map), + ); + +Map _$NamedAuthInfoToJson(NamedAuthInfo instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('name', instance.name); + writeNotNull('user', instance.user); + return val; +} diff --git a/lib/src/models/named_cluster.dart b/lib/src/models/named_cluster.dart new file mode 100644 index 0000000..e3d261e --- /dev/null +++ b/lib/src/models/named_cluster.dart @@ -0,0 +1,42 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:kubeconfig/src/models/cluster.dart'; +import 'package:meta/meta.dart'; + +part 'named_cluster.g.dart'; + +/// {@template named_cluster} +/// NamedCluster relates nicknames to cluster information. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class NamedCluster extends Equatable { + /// {@macro named_cluster} + const NamedCluster({ + required this.name, + required this.cluster, + }); + + /// Creates a new instance from json. + factory NamedCluster.fromJson(Map json) => + _$NamedClusterFromJson(json); + + /// Converts to json. + Map toJson() => _$NamedClusterToJson(this); + + /// Name is the nickname for this Cluster. + @JsonKey(name: 'name') + final String? name; + + /// Cluster holds the cluster information. + @JsonKey(name: 'cluster') + final Cluster? cluster; + + @override + List get props => []; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/named_cluster.g.dart b/lib/src/models/named_cluster.g.dart new file mode 100644 index 0000000..2ef0512 --- /dev/null +++ b/lib/src/models/named_cluster.g.dart @@ -0,0 +1,92 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'named_cluster.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$NamedClusterCWProxy { + NamedCluster name(String? name); + + NamedCluster cluster(Cluster? cluster); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `NamedCluster(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// NamedCluster(...).copyWith(id: 12, name: "My name") + /// ```` + NamedCluster call({ + String? name, + Cluster? cluster, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfNamedCluster.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfNamedCluster.copyWith.fieldName(...)` +class _$NamedClusterCWProxyImpl implements _$NamedClusterCWProxy { + const _$NamedClusterCWProxyImpl(this._value); + + final NamedCluster _value; + + @override + NamedCluster name(String? name) => this(name: name); + + @override + NamedCluster cluster(Cluster? cluster) => this(cluster: cluster); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `NamedCluster(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// NamedCluster(...).copyWith(id: 12, name: "My name") + /// ```` + NamedCluster call({ + Object? name = const $CopyWithPlaceholder(), + Object? cluster = const $CopyWithPlaceholder(), + }) { + return NamedCluster( + name: name == const $CopyWithPlaceholder() + ? _value.name + // ignore: cast_nullable_to_non_nullable + : name as String?, + cluster: cluster == const $CopyWithPlaceholder() + ? _value.cluster + // ignore: cast_nullable_to_non_nullable + : cluster as Cluster?, + ); + } +} + +extension $NamedClusterCopyWith on NamedCluster { + /// Returns a callable class that can be used as follows: `instanceOfNamedCluster.copyWith(...)` or like so:`instanceOfNamedCluster.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$NamedClusterCWProxy get copyWith => _$NamedClusterCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NamedCluster _$NamedClusterFromJson(Map json) => NamedCluster( + name: json['name'] as String?, + cluster: json['cluster'] == null + ? null + : Cluster.fromJson(json['cluster'] as Map), + ); + +Map _$NamedClusterToJson(NamedCluster instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('name', instance.name); + writeNotNull('cluster', instance.cluster); + return val; +} diff --git a/lib/src/models/named_context.dart b/lib/src/models/named_context.dart new file mode 100644 index 0000000..4f7b602 --- /dev/null +++ b/lib/src/models/named_context.dart @@ -0,0 +1,45 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:kubeconfig/src/models/context.dart'; +import 'package:meta/meta.dart'; + +part 'named_context.g.dart'; + +/// {@template named_context} +/// NamedContext relates nicknames to context information. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class NamedContext extends Equatable { + /// {@macro named_context} + const NamedContext({ + required this.name, + required this.context, + }); + + /// Creates a new instance from json. + factory NamedContext.fromJson(Map json) => + _$NamedContextFromJson(json); + + /// Converts to json. + Map toJson() => _$NamedContextToJson(this); + + /// Name is the nickname for this Context + @JsonKey(name: 'name') + final String? name; + + /// Context holds the context information + @JsonKey(name: 'context') + final Context? context; + + @override + List get props => [ + name, + context, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/named_context.g.dart b/lib/src/models/named_context.g.dart new file mode 100644 index 0000000..2346ede --- /dev/null +++ b/lib/src/models/named_context.g.dart @@ -0,0 +1,92 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'named_context.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$NamedContextCWProxy { + NamedContext name(String? name); + + NamedContext context(Context? context); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `NamedContext(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// NamedContext(...).copyWith(id: 12, name: "My name") + /// ```` + NamedContext call({ + String? name, + Context? context, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfNamedContext.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfNamedContext.copyWith.fieldName(...)` +class _$NamedContextCWProxyImpl implements _$NamedContextCWProxy { + const _$NamedContextCWProxyImpl(this._value); + + final NamedContext _value; + + @override + NamedContext name(String? name) => this(name: name); + + @override + NamedContext context(Context? context) => this(context: context); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `NamedContext(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// NamedContext(...).copyWith(id: 12, name: "My name") + /// ```` + NamedContext call({ + Object? name = const $CopyWithPlaceholder(), + Object? context = const $CopyWithPlaceholder(), + }) { + return NamedContext( + name: name == const $CopyWithPlaceholder() + ? _value.name + // ignore: cast_nullable_to_non_nullable + : name as String?, + context: context == const $CopyWithPlaceholder() + ? _value.context + // ignore: cast_nullable_to_non_nullable + : context as Context?, + ); + } +} + +extension $NamedContextCopyWith on NamedContext { + /// Returns a callable class that can be used as follows: `instanceOfNamedContext.copyWith(...)` or like so:`instanceOfNamedContext.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$NamedContextCWProxy get copyWith => _$NamedContextCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +NamedContext _$NamedContextFromJson(Map json) => NamedContext( + name: json['name'] as String?, + context: json['context'] == null + ? null + : Context.fromJson(json['context'] as Map), + ); + +Map _$NamedContextToJson(NamedContext instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('name', instance.name); + writeNotNull('context', instance.context); + return val; +} diff --git a/lib/src/models/preferences.dart b/lib/src/models/preferences.dart new file mode 100644 index 0000000..cfc1b17 --- /dev/null +++ b/lib/src/models/preferences.dart @@ -0,0 +1,38 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:meta/meta.dart'; + +part 'preferences.g.dart'; + +/// {@template preferences} +/// Preferences holds general information to be use for cli interactions. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class Preferences extends Equatable { + /// {@macro preferences} + const Preferences({ + required this.colors, + }); + + /// Creates a new instance from json. + factory Preferences.fromJson(Map json) => + _$PreferencesFromJson(json); + + /// Converts to json. + Map toJson() => _$PreferencesToJson(this); + + /// Enable colors. + @JsonKey(name: 'colors') + final bool? colors; + + @override + List get props => [ + colors, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/preferences.g.dart b/lib/src/models/preferences.g.dart new file mode 100644 index 0000000..f966161 --- /dev/null +++ b/lib/src/models/preferences.g.dart @@ -0,0 +1,77 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'preferences.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$PreferencesCWProxy { + Preferences colors(bool? colors); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Preferences(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Preferences(...).copyWith(id: 12, name: "My name") + /// ```` + Preferences call({ + bool? colors, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfPreferences.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfPreferences.copyWith.fieldName(...)` +class _$PreferencesCWProxyImpl implements _$PreferencesCWProxy { + const _$PreferencesCWProxyImpl(this._value); + + final Preferences _value; + + @override + Preferences colors(bool? colors) => this(colors: colors); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Preferences(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// Preferences(...).copyWith(id: 12, name: "My name") + /// ```` + Preferences call({ + Object? colors = const $CopyWithPlaceholder(), + }) { + return Preferences( + colors: colors == const $CopyWithPlaceholder() + ? _value.colors + // ignore: cast_nullable_to_non_nullable + : colors as bool?, + ); + } +} + +extension $PreferencesCopyWith on Preferences { + /// Returns a callable class that can be used as follows: `instanceOfPreferences.copyWith(...)` or like so:`instanceOfPreferences.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$PreferencesCWProxy get copyWith => _$PreferencesCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Preferences _$PreferencesFromJson(Map json) => Preferences( + colors: json['colors'] as bool?, + ); + +Map _$PreferencesToJson(Preferences instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('colors', instance.colors); + return val; +} diff --git a/lib/src/models/validation_result.dart b/lib/src/models/validation_result.dart new file mode 100644 index 0000000..91e4616 --- /dev/null +++ b/lib/src/models/validation_result.dart @@ -0,0 +1,45 @@ +import 'package:copy_with_extension/copy_with_extension.dart'; +import 'package:equatable/equatable.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:kubeconfig/src/enums/validation_code.dart'; +import 'package:meta/meta.dart'; + +part 'validation_result.g.dart'; + +/// {@template validation_result} +/// Kubeconfig validation result. +/// {@endtemplate} +@CopyWith() +@JsonSerializable(includeIfNull: false) +@immutable +class ValidationResult extends Equatable { + /// {@macro validation_result} + const ValidationResult({ + required this.code, + this.description, + }); + + /// Creates a new instance from json. + factory ValidationResult.fromJson(Map json) => + _$ValidationResultFromJson(json); + + /// Converts to json. + Map toJson() => _$ValidationResultToJson(this); + + /// Validation code. + @JsonKey(name: 'code') + final ValidationCode code; + + /// Validation description. + @JsonKey(name: 'description') + final String? description; + + @override + List get props => [ + code, + description, + ]; + + @override + bool get stringify => true; +} diff --git a/lib/src/models/validation_result.g.dart b/lib/src/models/validation_result.g.dart new file mode 100644 index 0000000..999300d --- /dev/null +++ b/lib/src/models/validation_result.g.dart @@ -0,0 +1,140 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'validation_result.dart'; + +// ************************************************************************** +// CopyWithGenerator +// ************************************************************************** + +abstract class _$ValidationResultCWProxy { + ValidationResult code(ValidationCode code); + + ValidationResult description(String? description); + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `ValidationResult(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// ValidationResult(...).copyWith(id: 12, name: "My name") + /// ```` + ValidationResult call({ + ValidationCode? code, + String? description, + }); +} + +/// Proxy class for `copyWith` functionality. This is a callable class and can be used as follows: `instanceOfValidationResult.copyWith(...)`. Additionally contains functions for specific fields e.g. `instanceOfValidationResult.copyWith.fieldName(...)` +class _$ValidationResultCWProxyImpl implements _$ValidationResultCWProxy { + const _$ValidationResultCWProxyImpl(this._value); + + final ValidationResult _value; + + @override + ValidationResult code(ValidationCode code) => this(code: code); + + @override + ValidationResult description(String? description) => + this(description: description); + + @override + + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `ValidationResult(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. + /// + /// Usage + /// ```dart + /// ValidationResult(...).copyWith(id: 12, name: "My name") + /// ```` + ValidationResult call({ + Object? code = const $CopyWithPlaceholder(), + Object? description = const $CopyWithPlaceholder(), + }) { + return ValidationResult( + code: code == const $CopyWithPlaceholder() || code == null + ? _value.code + // ignore: cast_nullable_to_non_nullable + : code as ValidationCode, + description: description == const $CopyWithPlaceholder() + ? _value.description + // ignore: cast_nullable_to_non_nullable + : description as String?, + ); + } +} + +extension $ValidationResultCopyWith on ValidationResult { + /// Returns a callable class that can be used as follows: `instanceOfValidationResult.copyWith(...)` or like so:`instanceOfValidationResult.copyWith.fieldName(...)`. + // ignore: library_private_types_in_public_api + _$ValidationResultCWProxy get copyWith => _$ValidationResultCWProxyImpl(this); +} + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ValidationResult _$ValidationResultFromJson(Map json) => + ValidationResult( + code: $enumDecode(_$ValidationCodeEnumMap, json['code']), + description: json['description'] as String?, + ); + +Map _$ValidationResultToJson(ValidationResult instance) { + final val = { + 'code': _$ValidationCodeEnumMap[instance.code]!, + }; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('description', instance.description); + return val; +} + +const _$ValidationCodeEnumMap = { + ValidationCode.valid: 'valid', + ValidationCode.clustersRequired: 'clustersRequired', + ValidationCode.contextsRequired: 'contextsRequired', + ValidationCode.usersRequired: 'usersRequired', + ValidationCode.nameRequiredForNamedCluster: 'nameRequiredForNamedCluster', + ValidationCode.nameRequiredForNamedContext: 'nameRequiredForNamedContext', + ValidationCode.nameRequiredForNamedUser: 'nameRequiredForNamedUser', + ValidationCode.clusterRequiredForNamedCluster: + 'clusterRequiredForNamedCluster', + ValidationCode.contextRequiredForNamedContext: + 'contextRequiredForNamedContext', + ValidationCode.userRequiredForNamedUser: 'userRequiredForNamedUser', + ValidationCode.serverRequiredForCluster: 'serverRequiredForCluster', + ValidationCode.clusterRequiredForContext: 'clusterRequiredForContext', + ValidationCode.userRequiredForContext: 'userRequiredForContext', + ValidationCode.namedClusterDuplicate: 'namedClusterDuplicate', + ValidationCode.namedContextDuplicate: 'namedContextDuplicate', + ValidationCode.namedUserDuplicate: 'namedUserDuplicate', + ValidationCode.currentContextNotFound: 'currentContextNotFound', + ValidationCode.clusterNotFoundForContext: 'clusterNotFoundForContext', + ValidationCode.userNotFoundForContext: 'userNotFoundForContext', + ValidationCode.namespaceInvalidMaxLengthForContext: + 'namespaceInvalidMaxLengthForContext', + ValidationCode.namespaceFormatNotMatchForContext: + 'namespaceFormatNotMatchForContext', + ValidationCode.certificateAuthorityErrorForCluster: + 'certificateAuthorityErrorForCluster', + ValidationCode.certificateAuthorityFileErrorForCluster: + 'certificateAuthorityFileErrorForCluster', + ValidationCode.proxyUrlInvalidForCluster: 'proxyUrlInvalidForCluster', + ValidationCode.proxyUrlInvalidSchemeForCluster: + 'proxyUrlInvalidSchemeForCluster', + ValidationCode.clientCertErrorForUser: 'clientCertErrorForUser', + ValidationCode.clientKeyErrorForUser: 'clientKeyErrorForUser', + ValidationCode.clientKeyNotFoundForUser: 'clientKeyNotFoundForUser', + ValidationCode.clientCertFileErrorForUser: 'clientCertFileErrorForUser', + ValidationCode.clientKeyFileErrorForUser: 'clientKeyFileErrorForUser', + ValidationCode.authProviderAndExecErrorForUser: + 'authProviderAndExecErrorForUser', + ValidationCode.execCommandNotFoundForUser: 'execCommandNotFoundForUser', + ValidationCode.execApiVersionNotFoundForUser: 'execApiVersionNotFoundForUser', + ValidationCode.execEnvNameNotFoundForUser: 'execEnvNameNotFoundForUser', + ValidationCode.moreThanOneAuthFoundForUser: 'moreThanOneAuthFoundForUser', + ValidationCode.impersonatingErrorForUser: 'impersonatingErrorForUser', +}; diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..2ca13b3 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,27 @@ +name: kubeconfig +description: Kubeconfig utility. Validate, convert, and merge kubeconfig files. +version: 1.0.0+1 +repository: https://github.com/fatihsever/kubeconfig-lib + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + collection: ^1.18.0 + copy_with_extension: ^5.0.4 + equatable: ^2.0.5 + json_annotation: ^4.8.1 + meta: ^1.11.0 + yaml: ^3.1.2 + +dev_dependencies: + build_runner: ^2.4.8 + copy_with_extension_gen: ^5.0.4 + json_serializable: ^6.7.1 + mocktail: ^1.0.2 + test: ^1.25.1 + very_good_analysis: ^5.1.0 + +screenshots: + - description: The kubeconfig package logo. + path: assets/logo.webp diff --git a/test/files/README.md b/test/files/README.md new file mode 100644 index 0000000..0722c10 --- /dev/null +++ b/test/files/README.md @@ -0,0 +1 @@ +> (!) Files, keys and tokens in this directory are generated for testing purposes only. diff --git a/test/files/cert/README.md b/test/files/cert/README.md new file mode 100644 index 0000000..f39c9c5 --- /dev/null +++ b/test/files/cert/README.md @@ -0,0 +1,29 @@ +## Fake certificate (self-signed) + +> (!) Certificates and private keys in this directory are generated for testing purposes only. + +**CA:** +```bash +openssl genrsa 2048 > ca.key && +openssl req -new -x509 -nodes -days 365000 -key ca.key -out ca.crt # set the CN to 127.0.0.1 +``` + +**CSR and Private Key:** +```bash +openssl req -new -newkey rsa:2048 -nodes -out example.csr -keyout example.key -subj "/C=US/ST=State/L=City/O=Example/OU=IT/CN=*.example.com" +``` + +**Public Key:** +```bash +openssl x509 -signkey example.key -in example.csr -req -days 3650 -out example.crt +``` + +**Base64 Encoded Private Key:** +```bash +base64 -i example.key -o example_key_base64.txt +``` + +**Base64 Encoded Public Key:** +```bash +base64 -i example.crt -o example_crt_base64.txt +``` diff --git a/test/files/cert/ca.crt b/test/files/cert/ca.crt new file mode 100644 index 0000000..f32825a --- /dev/null +++ b/test/files/cert/ca.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDPDCCAiQCCQCfJtGqdpCEOjANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJV +UzEOMAwGA1UECAwFU3RhdGUxDTALBgNVBAcMBENpdHkxEDAOBgNVBAoMB0NvbXBh +bnkxCzAJBgNVBAsMAklUMRIwEAYDVQQDDAkxMjcuMC4wLjEwIBcNMjMwMjIxMTY0 +NDE1WhgPMzAyMjA2MjQxNjQ0MTVaMF8xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVT +dGF0ZTENMAsGA1UEBwwEQ2l0eTEQMA4GA1UECgwHQ29tcGFueTELMAkGA1UECwwC +SVQxEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMjz4tVs1CmSoOMurrRoGqpnjfOgoXZYYcBQXntFJATwh4pIv4drXMok +51PTN66Mr9yg8YVDPiqJuVLrB739eKzX3NijqY/xmnjIjoQOOb8IjDpuTqdOQHaN +DtT0vghl/XjsUJAEkpCwkt7lxMrj4wfvP37qX24uepvtPeTFVQ/v9X6t9sAGNdnk +ojAjGZ8BRApUkXI+Soap68ygD71hrhkXCQcXkQt2aGcCWauySIis7iwgjs9TU3Ds +3EYoGlfHsNrzjE8qiNWEq3+5RIi7LbKfEXv4DJ/np852lAHP2i+MabnSoBKuG3j3 +WpC61wCde63pMGZ8oKFFjSIsPos186cCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA +VYmjGUoXE3czUPu69e22SFhQSYxypLeQKko/89R3a6qI4wcqcKqZtDMvdtU1AAw3 +0xBNnZzddTorPU3LjDD8fdo1vMbpeVYgXxgWR1KVB2D/cxPiSFIjfUYZpLCvcbgK +cvd6GsQ73JiS9KklOjRS3db8fBoEKoIUc/q4XNz/xEcubfs8Jedz9Hd6m+yuMzBn +jtbisCgB++yc4bZ98HGXyId8TXqNF0PcyG8q/ptj1/uqvoq55rUm9qt0JCKTW9d0 +UanG4uAF8hottm75kABHvImkR9BYh5whmeHoQiSTDXFdGZd032CM7+AXHIO4Yxiq +tQbpupm3FUh+hWzx9nVxyg== +-----END CERTIFICATE----- diff --git a/test/files/cert/ca.key b/test/files/cert/ca.key new file mode 100644 index 0000000..b34235f --- /dev/null +++ b/test/files/cert/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAyPPi1WzUKZKg4y6utGgaqmeN86ChdlhhwFBee0UkBPCHiki/ +h2tcyiTnU9M3royv3KDxhUM+Kom5UusHvf14rNfc2KOpj/GaeMiOhA45vwiMOm5O +p05Ado0O1PS+CGX9eOxQkASSkLCS3uXEyuPjB+8/fupfbi56m+095MVVD+/1fq32 +wAY12eSiMCMZnwFEClSRcj5KhqnrzKAPvWGuGRcJBxeRC3ZoZwJZq7JIiKzuLCCO +z1NTcOzcRigaV8ew2vOMTyqI1YSrf7lEiLstsp8Re/gMn+enznaUAc/aL4xpudKg +Eq4bePdakLrXAJ17rekwZnygoUWNIiw+izXzpwIDAQABAoIBAQCmgN3sdTX+FE5W +rvF27eNaWl9WBDyEsIqeLHl8rjdAGIRV4h1AeYbyv00lOZeje1Kj/n7gKm0yFdeG +itNpasI4hMuqfUEb0dZqSdM8PAVA8jYunANzwPTMxegKL5fdoZQ6Q6QlEITYelXX +do5uhhAxHN2BrXTQ+JYC6Lol+hOXFYYJoujuDGpJayBTC8i1enJZlPg88MctpXkA +xDvU+xtR/KRvhOAYM7KEvysG5KRJ+cXZCy6E+1Tz0vJmB+9QfoV75B2BJ/eB9rAl +oZsHYhMkDQyhvl2hkAildBVb+xfWngRlhwPpCKvxyRGc0CErxIJiFdfmmylwC5Cf +/hopfELxAoGBAO33KlGhF7GucAPzjxJqJQ8IjmIMrjVsdNMoXq2m37g7KPwu0gAz +A9wN1bG4i6tGuo60bMNICV3gfoDUul64Z79AsRwUXsGluwWrE2VT4x7IbWt32RG7 +QRYU5kH72HCB2j3WmwEfrH/JljaPDPVCPo8ux6p3RbBv8z5uF6WwcRp1AoGBANgu +n/wzQ1+bGD7wf0RnDavMs/Nm6nAFlWrUtp4O+Du1vqZc6yyYDNFr2Ed75cbRDllO +iBNzQOYFKNQbjM3AhIIwxcY5KtXqKjUDn4Xy/3CO8QyFkEnNfsdnuACPAHSxUTrL +6+32QactM4vKFD/0yR5+lUBxQqYHpEcf84xwWDorAoGAUTb843UmYAbXxhF27+L4 +GORjq8UGI8eLK5Holj2QtxDB0SetllHS7GRwXUJNsLvn6dJcGF3ajIaUxiVUIgWv +qs9KYvn0yQRmCu4zJW724cenyHjTxcBx2zZwy25HlUZMFLTMnBqSRd6n/KDf3Eiq +jzV5AY3JZAkhLFpoiazpPQ0CgYAmFSiXzAwNVowR4ln5GdJdtmTo9vNLoqAsvqYg +9/AgzKZ2Nh4zr+FqLv5dsWTL/l3xu5TbIE2Jd9U2cFgAku6E5MSiY8W5A1RGHIpI +lYMMOBIcq5a8eZfg1tOiPY7N/8KYgf3g4KW2Jo9TC9k/Xwbi+Vefj5Q3HVeCNA26 +arwQGwKBgQDo2dBlcSAulYO98HODjXUTyv/nnCAkAGF9MSoZFNe6Ye7kK/lVXqJx +x0Nwb4kBwb89AV2Fb8jzv2CNEkP1OhiFh51+d/qEyBLysTg029zOz0gdtGWSJbsK +7XvaZkpD1bbiVZ9JZnRyWbntq3lX7BUFj2/CF64z4HDApqQtOWchuw== +-----END RSA PRIVATE KEY----- diff --git a/test/files/cert/example.crt b/test/files/cert/example.crt new file mode 100644 index 0000000..c12758e --- /dev/null +++ b/test/files/cert/example.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQjCCAioCCQCDund76Kj5ujANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJV +UzEOMAwGA1UECAwFU3RhdGUxDTALBgNVBAcMBENpdHkxEDAOBgNVBAoMB0V4YW1w +bGUxCzAJBgNVBAsMAklUMRYwFAYDVQQDDA0qLmV4YW1wbGUuY29tMB4XDTIzMDIy +MTA4MzY1NVoXDTMzMDIxODA4MzY1NVowYzELMAkGA1UEBhMCVVMxDjAMBgNVBAgM +BVN0YXRlMQ0wCwYDVQQHDARDaXR5MRAwDgYDVQQKDAdFeGFtcGxlMQswCQYDVQQL +DAJJVDEWMBQGA1UEAwwNKi5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBANWyUr7V9WeZDEZsoarrfWYfQi5mpp9/s8csQOk8Ic9hkI9K +1jEKqyYYSvRmy+OVQtChbi7olKh1lLAD1AIzyL0ILYUu0Tn+m8gKhgFvK6ytvRVF +NWLOcXr0YPoR8AHzSziVcoLo+WzQCvmLJ0BgrO0t3DF6DJvupPmXVrTm4XdMNA7j +5WZ7KJzZrOG86zIvtjDpUxO++JgAgX220+gK2Zjr5xRfyp89hGGCD0yaxBSQ6+Ny +XrTpPe+HCAsSq6sOYpST8CmyiY8lkgCWy4muweSyT41ZoJKvy1fQOCLyKxUndwe/ +7Ce6m3JwqSHLzxZLLYyJIXWUP0g2fnkaKCcVR20CAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAI80XM7JsYEmWDnA6PrXzq2M6pNLtbQbwSt9+hbmsjFai3o4/LNQYrEcE +6BdfZaG9U5T7hV9n98DaxRh0tHmpNGMBsaIVLUjWddWsx9FB29yFZff95INSAx43 +VaO3or3DQH5ieWhPuwsS95VtVnwj837DyCzjCB1yDP5lyXsZAT6toM1cS/BTqYdC +aEk+mOFnhLtTJszeyWlx7Q63kUp6aEK+rByq3dh/wts+VzhP6CSJl1Ye4jVinwW6 +QLxmSmSSS6a1G9uVG5FHwAIrsAdl/ZcIM7HIhLEv27XmZFGiY4Tvkidjs4ic2GBX +26wPl03sqYudtE0qIhvWTL7GP6ipGw== +-----END CERTIFICATE----- diff --git a/test/files/cert/example.csr b/test/files/cert/example.csr new file mode 100644 index 0000000..feb4e73 --- /dev/null +++ b/test/files/cert/example.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICqDCCAZACAQAwYzELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYD +VQQHDARDaXR5MRAwDgYDVQQKDAdFeGFtcGxlMQswCQYDVQQLDAJJVDEWMBQGA1UE +AwwNKi5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANWyUr7V9WeZDEZsoarrfWYfQi5mpp9/s8csQOk8Ic9hkI9K1jEKqyYYSvRmy+OV +QtChbi7olKh1lLAD1AIzyL0ILYUu0Tn+m8gKhgFvK6ytvRVFNWLOcXr0YPoR8AHz +SziVcoLo+WzQCvmLJ0BgrO0t3DF6DJvupPmXVrTm4XdMNA7j5WZ7KJzZrOG86zIv +tjDpUxO++JgAgX220+gK2Zjr5xRfyp89hGGCD0yaxBSQ6+NyXrTpPe+HCAsSq6sO +YpST8CmyiY8lkgCWy4muweSyT41ZoJKvy1fQOCLyKxUndwe/7Ce6m3JwqSHLzxZL +LYyJIXWUP0g2fnkaKCcVR20CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCd1dOD +qV7coWMxmercG8PrtUsFdVE0Ky8Vja6Z8BaBxfWcNskn0ivmiiJlWTaUkt8e2/yt +LviFaKdlNlm/naOT9t+KAumqsm5KVZAtfqOYBEaFHvu2XVLzgiIZRLbdKYiGMpw5 +PObuXoLsCjkUKjOu3qyKGfoxFp68jxiybLxwn/99AXuzgIbHrkWfSbhjgnzxgApl +lzwQtblnUQm4z/AYmWKxsfY97FWzmbr7WCtBeyi0QC0v95kdHPwGbZVpiigEtWn6 +iQKk1BlIb6uu5/EnCMaWUuketa16jSLSD86Jkwl8oHsh6FZvDD79Uh80n3S9nxWR +QUPXkVqhd0x+kxZe +-----END CERTIFICATE REQUEST----- diff --git a/test/files/cert/example.key b/test/files/cert/example.key new file mode 100644 index 0000000..8e16850 --- /dev/null +++ b/test/files/cert/example.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDVslK+1fVnmQxG +bKGq631mH0IuZqaff7PHLEDpPCHPYZCPStYxCqsmGEr0ZsvjlULQoW4u6JSodZSw +A9QCM8i9CC2FLtE5/pvICoYBbyusrb0VRTViznF69GD6EfAB80s4lXKC6Pls0Ar5 +iydAYKztLdwxegyb7qT5l1a05uF3TDQO4+Vmeyic2azhvOsyL7Yw6VMTvviYAIF9 +ttPoCtmY6+cUX8qfPYRhgg9MmsQUkOvjcl606T3vhwgLEqurDmKUk/ApsomPJZIA +lsuJrsHksk+NWaCSr8tX0Dgi8isVJ3cHv+wnuptycKkhy88WSy2MiSF1lD9INn55 +GignFUdtAgMBAAECggEAC+N10wQYOQE8u5ZDkDy1pz7J8cboMitqlwQRQGiGAQGO +h0pEjEnpp57mXJ5zbV/abbztYlKyIoUYFoq/+rdizZFs5uHp5e4SQJjFR8MljN/F +iy9kfvC5Q3vhAUiKL7GXV7iIvFu1tKYGVke1kVFPjYplm6MMnIg0SWZv/nRxyq8q +kFcUvJEExDJc5l9Bi1zD+W+YsMq9GRuq5rmic7bXtAF4MRN+fkvt1rGscnIowU+g +wT+0t9i3gei5vLfvQeu0+Ap2CN0LlCg9w2pMp9Usd84kW6ro6WOscyQd0h2GV4ch +eKzJehw53mre6NgZ35gRFXh4Utjq3g8TL14GP4xuwQKBgQD1VTLqX15EIZnkNaP1 +zxEnEVhUM0oMnj6YqkbUoU/do2ofibUoOc84aPKNqDUtdyEojV9tGXyhVzGKjsr5 +MSKVo7+PWBCzefNAFvz4cu2ab2GBdA0a0lTvBGzrzTXb5GR/Ol7g+YOyN2FtuBBM +eJPtL17He8Hkc8HrqeH9XEv/aQKBgQDe/Psw+hH8aMYYqh7cxNXdL+LbLks48NtT +hgYsHlYyqpOZlVxyPoCu7cgovjFnv9CDYUafoPDMt8X/a5eaMUCOd9IgRPzxYb4N +IID2v4+P3iwkVbv7RLzACuMpEjxY8k7nhrnIjgHUrtxN1D8KbmVVmdyRohuJqgzZ +scj5rCALZQKBgCq0efhyQWZ6st8Wt0PCl6nFSyrdArbPlPXeLhY1PkHGgGKdBfvK +lFetbQtbjGYtpof4k/PZy+gJ1YXY9VwLQYnqxx2cpsuXHtC5L6/P0axgVwjBusZA +dqhkjNE/F3D/gL7k2j8vL82F9l+y+qNVGerfpA/1avrpa4gqOjxwJIqBAoGATEUb +ZdUi8cKkfysxAzIQNGd8oJtk/0Tiv97Hna+CrDHL6mw8Apd+TFbob4cePu5M06Mi +FNdnhZ4WCxcx83uFKTWymXb/TVCxQKwtcDh1UjAbyRHKCleod8dBi3rBSWsXsflS +8lYgKi7lC3ndViQMZQsLdoSMBrozSwKUS1GkZEECgYAs19Qs6waUUmZ7mCJDGGlq +n6qTBvYb9bnGJux0j8MaOTtLmT/rQzAft83aNLoEHffgeEBWGpDvyTu7jMAXkEzk +xKLbNg52c82pHVn4dqTGOUQ376/Wy1kS9daBSHcieAF9vuomzXCYp+O4Hs+r1qje +cQzJCtoXWcUie2jCdGSUBg== +-----END PRIVATE KEY----- diff --git a/test/files/cert/example_crt_base64.txt b/test/files/cert/example_crt_base64.txt new file mode 100644 index 0000000..e83e3f3 --- /dev/null +++ b/test/files/cert/example_crt_base64.txt @@ -0,0 +1 @@ +LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRakNDQWlvQ0NRQ0R1bmQ3NktqNXVqQU5CZ2txaGtpRzl3MEJBUXNGQURCak1Rc3dDUVlEVlFRR0V3SlYKVXpFT01Bd0dBMVVFQ0F3RlUzUmhkR1V4RFRBTEJnTlZCQWNNQkVOcGRIa3hFREFPQmdOVkJBb01CMFY0WVcxdwpiR1V4Q3pBSkJnTlZCQXNNQWtsVU1SWXdGQVlEVlFRRERBMHFMbVY0WVcxd2JHVXVZMjl0TUI0WERUSXpNREl5Ck1UQTRNelkxTlZvWERUTXpNREl4T0RBNE16WTFOVm93WXpFTE1Ba0dBMVVFQmhNQ1ZWTXhEakFNQmdOVkJBZ00KQlZOMFlYUmxNUTB3Q3dZRFZRUUhEQVJEYVhSNU1SQXdEZ1lEVlFRS0RBZEZlR0Z0Y0d4bE1Rc3dDUVlEVlFRTApEQUpKVkRFV01CUUdBMVVFQXd3TktpNWxlR0Z0Y0d4bExtTnZiVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBTld5VXI3VjlXZVpERVpzb2FycmZXWWZRaTVtcHA5L3M4Y3NRT2s4SWM5aGtJOUsKMWpFS3F5WVlTdlJteStPVlF0Q2hiaTdvbEtoMWxMQUQxQUl6eUwwSUxZVXUwVG4rbThnS2hnRnZLNnl0dlJWRgpOV0xPY1hyMFlQb1I4QUh6U3ppVmNvTG8rV3pRQ3ZtTEowQmdyTzB0M0RGNkRKdnVwUG1YVnJUbTRYZE1OQTdqCjVXWjdLSnpack9HODZ6SXZ0akRwVXhPKytKZ0FnWDIyMCtnSzJaanI1eFJmeXA4OWhHR0NEMHlheEJTUTYrTnkKWHJUcFBlK0hDQXNTcTZzT1lwU1Q4Q215aVk4bGtnQ1d5NG11d2VTeVQ0MVpvSkt2eTFmUU9DTHlLeFVuZHdlLwo3Q2U2bTNKd3FTSEx6eFpMTFl5SklYV1VQMGcyZm5rYUtDY1ZSMjBDQXdFQUFUQU5CZ2txaGtpRzl3MEJBUXNGCkFBT0NBUUVBSTgwWE03SnNZRW1XRG5BNlByWHpxMk02cE5MdGJRYndTdDkraGJtc2pGYWkzbzQvTE5RWXJFY0UKNkJkZlphRzlVNVQ3aFY5bjk4RGF4UmgwdEhtcE5HTUJzYUlWTFVqV2RkV3N4OUZCMjl5RlpmZjk1SU5TQXg0MwpWYU8zb3IzRFFINWllV2hQdXdzUzk1VnRWbndqODM3RHlDempDQjF5RFA1bHlYc1pBVDZ0b00xY1MvQlRxWWRDCmFFayttT0ZuaEx0VEpzemV5V2x4N1E2M2tVcDZhRUsrckJ5cTNkaC93dHMrVnpoUDZDU0psMVllNGpWaW53VzYKUUx4bVNtU1NTNmExRzl1Vkc1Rkh3QUlyc0FkbC9aY0lNN0hJaExFdjI3WG1aRkdpWTRUdmtpZGpzNGljMkdCWAoyNndQbDAzc3FZdWR0RTBxSWh2V1RMN0dQNmlwR3c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== diff --git a/test/files/cert/example_key_base64.txt b/test/files/cert/example_key_base64.txt new file mode 100644 index 0000000..b328d1a --- /dev/null +++ b/test/files/cert/example_key_base64.txt @@ -0,0 +1 @@ +LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRRFZzbEsrMWZWbm1ReEcKYktHcTYzMW1IMEl1WnFhZmY3UEhMRURwUENIUFlaQ1BTdFl4Q3FzbUdFcjBac3ZqbFVMUW9XNHU2SlNvZFpTdwpBOVFDTThpOUNDMkZMdEU1L3B2SUNvWUJieXVzcmIwVlJUVml6bkY2OUdENkVmQUI4MHM0bFhLQzZQbHMwQXI1Cml5ZEFZS3p0TGR3eGVneWI3cVQ1bDFhMDV1RjNURFFPNCtWbWV5aWMyYXpodk9zeUw3WXc2Vk1UdnZpWUFJRjkKdHRQb0N0bVk2K2NVWDhxZlBZUmhnZzlNbXNRVWtPdmpjbDYwNlQzdmh3Z0xFcXVyRG1LVWsvQXBzb21QSlpJQQpsc3VKcnNIa3NrK05XYUNTcjh0WDBEZ2k4aXNWSjNjSHYrd251cHR5Y0traHk4OFdTeTJNaVNGMWxEOUlObjU1CkdpZ25GVWR0QWdNQkFBRUNnZ0VBQytOMTB3UVlPUUU4dTVaRGtEeTFwejdKOGNib01pdHFsd1FSUUdpR0FRR08KaDBwRWpFbnBwNTdtWEo1emJWL2FiYnp0WWxLeUlvVVlGb3EvK3JkaXpaRnM1dUhwNWU0U1FKakZSOE1sak4vRgppeTlrZnZDNVEzdmhBVWlLTDdHWFY3aUl2RnUxdEtZR1ZrZTFrVkZQallwbG02TU1uSWcwU1dadi9uUnh5cThxCmtGY1V2SkVFeERKYzVsOUJpMXpEK1crWXNNcTlHUnVxNXJtaWM3Ylh0QUY0TVJOK2ZrdnQxckdzY25Jb3dVK2cKd1QrMHQ5aTNnZWk1dkxmdlFldTArQXAyQ04wTGxDZzl3MnBNcDlVc2Q4NGtXNnJvNldPc2N5UWQwaDJHVjRjaAplS3pKZWh3NTNtcmU2TmdaMzVnUkZYaDRVdGpxM2c4VEwxNEdQNHh1d1FLQmdRRDFWVExxWDE1RUlabmtOYVAxCnp4RW5FVmhVTTBvTW5qNllxa2JVb1UvZG8yb2ZpYlVvT2M4NGFQS05xRFV0ZHlFb2pWOXRHWHloVnpHS2pzcjUKTVNLVm83K1BXQkN6ZWZOQUZ2ejRjdTJhYjJHQmRBMGEwbFR2Qkd6cnpUWGI1R1IvT2w3ZytZT3lOMkZ0dUJCTQplSlB0TDE3SGU4SGtjOEhycWVIOVhFdi9hUUtCZ1FEZS9Qc3craEg4YU1ZWXFoN2N4TlhkTCtMYkxrczQ4TnRUCmhnWXNIbFl5cXBPWmxWeHlQb0N1N2Nnb3ZqRm52OUNEWVVhZm9QRE10OFgvYTVlYU1VQ09kOUlnUlB6eFliNE4KSUlEMnY0K1AzaXdrVmJ2N1JMekFDdU1wRWp4WThrN25ocm5JamdIVXJ0eE4xRDhLYm1WVm1keVJvaHVKcWd6WgpzY2o1ckNBTFpRS0JnQ3EwZWZoeVFXWjZzdDhXdDBQQ2w2bkZTeXJkQXJiUGxQWGVMaFkxUGtIR2dHS2RCZnZLCmxGZXRiUXRiakdZdHBvZjRrL1BaeStnSjFZWFk5VndMUVlucXh4MmNwc3VYSHRDNUw2L1AwYXhnVndqQnVzWkEKZHFoa2pORS9GM0QvZ0w3azJqOHZMODJGOWwreStxTlZHZXJmcEEvMWF2cnBhNGdxT2p4d0pJcUJBb0dBVEVVYgpaZFVpOGNLa2Z5c3hBeklRTkdkOG9KdGsvMFRpdjk3SG5hK0NyREhMNm13OEFwZCtURmJvYjRjZVB1NU0wNk1pCkZOZG5oWjRXQ3hjeDgzdUZLVFd5bVhiL1RWQ3hRS3d0Y0RoMVVqQWJ5UkhLQ2xlb2Q4ZEJpM3JCU1dzWHNmbFMKOGxZZ0tpN2xDM25kVmlRTVpRc0xkb1NNQnJvelN3S1VTMUdrWkVFQ2dZQXMxOVFzNndhVVVtWjdtQ0pER0dscQpuNnFUQnZZYjlibkdKdXgwajhNYU9UdExtVC9yUXpBZnQ4M2FOTG9FSGZmZ2VFQldHcER2eVR1N2pNQVhrRXprCnhLTGJOZzUyYzgycEhWbjRkcVRHT1VRMzc2L1d5MWtTOWRhQlNIY2llQUY5dnVvbXpYQ1lwK080SHMrcjFxamUKY1F6SkN0b1hXY1VpZTJqQ2RHU1VCZz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/test/files/empty.yaml b/test/files/empty.yaml new file mode 100644 index 0000000..e69de29 diff --git a/test/files/invalid.json b/test/files/invalid.json new file mode 100644 index 0000000..821c0a0 --- /dev/null +++ b/test/files/invalid.json @@ -0,0 +1 @@ +`invalid` diff --git a/test/files/invalid.yaml b/test/files/invalid.yaml new file mode 100644 index 0000000..821c0a0 --- /dev/null +++ b/test/files/invalid.yaml @@ -0,0 +1 @@ +`invalid` diff --git a/test/files/invalid_cluster_certificate_both.yaml b/test/files/invalid_cluster_certificate_both.yaml new file mode 100644 index 0000000..4f2d672 --- /dev/null +++ b/test/files/invalid_cluster_certificate_both.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority: test/files/cert/ca.crt + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_cluster_certificate_file.yaml b/test/files/invalid_cluster_certificate_file.yaml new file mode 100644 index 0000000..8a87d50 --- /dev/null +++ b/test/files/invalid_cluster_certificate_file.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority: test/files/cert/missing.crt + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_cluster_proxyurl.yaml b/test/files/invalid_cluster_proxyurl.yaml new file mode 100644 index 0000000..e346aca --- /dev/null +++ b/test/files/invalid_cluster_proxyurl.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + proxy-url: ://invalid-uri + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_cluster_proxyurl_scheme.yaml b/test/files/invalid_cluster_proxyurl_scheme.yaml new file mode 100644 index 0000000..e49676e --- /dev/null +++ b/test/files/invalid_cluster_proxyurl_scheme.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + proxy-url: ldap://invalid-scheme + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_cluster_server.yaml b/test/files/invalid_cluster_server.yaml new file mode 100644 index 0000000..3935e36 --- /dev/null +++ b/test/files/invalid_cluster_server.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_clusters_cluster.yaml b/test/files/invalid_clusters_cluster.yaml new file mode 100644 index 0000000..b10da73 --- /dev/null +++ b/test/files/invalid_clusters_cluster.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +clusters: + - name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_clusters_duplicate.yaml b/test/files/invalid_clusters_duplicate.yaml new file mode 100644 index 0000000..d9fdb2e --- /dev/null +++ b/test/files/invalid_clusters_duplicate.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example + - cluster: + insecure-skip-tls-verify: true + server: https://kubernetes.docker.internal:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_clusters_name.yaml b/test/files/invalid_clusters_name.yaml new file mode 100644 index 0000000..6bb2320 --- /dev/null +++ b/test/files/invalid_clusters_name.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - name: example + user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/test/files/invalid_clusters_required.yaml b/test/files/invalid_clusters_required.yaml new file mode 100644 index 0000000..e89811c --- /dev/null +++ b/test/files/invalid_clusters_required.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_context_cluster.yaml b/test/files/invalid_context_cluster.yaml new file mode 100644 index 0000000..2fc90b6 --- /dev/null +++ b/test/files/invalid_context_cluster.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_context_cluster_missing.yaml b/test/files/invalid_context_cluster_missing.yaml new file mode 100644 index 0000000..3ed7799 --- /dev/null +++ b/test/files/invalid_context_cluster_missing.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: missing + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_context_namespace_format.yaml b/test/files/invalid_context_namespace_format.yaml new file mode 100644 index 0000000..08d891f --- /dev/null +++ b/test/files/invalid_context_namespace_format.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + namespace: must_be_lower_case_@lphanumeric_charact€rs_with_da$h + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_context_namespace_length.yaml b/test/files/invalid_context_namespace_length.yaml new file mode 100644 index 0000000..d85da0d --- /dev/null +++ b/test/files/invalid_context_namespace_length.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + namespace: max-length-cannot-be-greater-than-63-max-length-cannot-be-greater-than-63 + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_context_user.yaml b/test/files/invalid_context_user.yaml new file mode 100644 index 0000000..d83b893 --- /dev/null +++ b/test/files/invalid_context_user.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_context_user_missing.yaml b/test/files/invalid_context_user_missing.yaml new file mode 100644 index 0000000..cb96022 --- /dev/null +++ b/test/files/invalid_context_user_missing.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: missing + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_contexts_context.yaml b/test/files/invalid_contexts_context.yaml new file mode 100644 index 0000000..8b8c581 --- /dev/null +++ b/test/files/invalid_contexts_context.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_contexts_duplicate.yaml b/test/files/invalid_contexts_duplicate.yaml new file mode 100644 index 0000000..a64f9ae --- /dev/null +++ b/test/files/invalid_contexts_duplicate.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_contexts_name.yaml b/test/files/invalid_contexts_name.yaml new file mode 100644 index 0000000..cc7aaa0 --- /dev/null +++ b/test/files/invalid_contexts_name.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example +current-context: example +kind: Config +preferences: {} +users: + - name: example + user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/test/files/invalid_contexts_required.yaml b/test/files/invalid_contexts_required.yaml new file mode 100644 index 0000000..bb63e49 --- /dev/null +++ b/test/files/invalid_contexts_required.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_current_context.yaml b/test/files/invalid_current_context.yaml new file mode 100644 index 0000000..740ecc0 --- /dev/null +++ b/test/files/invalid_current_context.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: missing +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_user_auth_provider.yaml b/test/files/invalid_user_auth_provider.yaml new file mode 100644 index 0000000..4de3ea5 --- /dev/null +++ b/test/files/invalid_user_auth_provider.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + auth-provider: + config: + client-id: kubernetes + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + name: example diff --git a/test/files/invalid_user_certificate_both.yaml b/test/files/invalid_user_certificate_both.yaml new file mode 100644 index 0000000..278f108 --- /dev/null +++ b/test/files/invalid_user_certificate_both.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate: test/files/cert/example.crt + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_user_certificate_file.yaml b/test/files/invalid_user_certificate_file.yaml new file mode 100644 index 0000000..8f9a356 --- /dev/null +++ b/test/files/invalid_user_certificate_file.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate: test/files/cert/missing.crt + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/invalid_user_clientkey_both.yaml b/test/files/invalid_user_clientkey_both.yaml new file mode 100644 index 0000000..4f2060b --- /dev/null +++ b/test/files/invalid_user_clientkey_both.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + client-key: test/files/cert/example.key + name: example diff --git a/test/files/invalid_user_clientkey_file.yaml b/test/files/invalid_user_clientkey_file.yaml new file mode 100644 index 0000000..8ed511a --- /dev/null +++ b/test/files/invalid_user_clientkey_file.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key: test/files/missing.key + name: example diff --git a/test/files/invalid_user_clientkey_missing.yaml b/test/files/invalid_user_clientkey_missing.yaml new file mode 100644 index 0000000..c06c3f6 --- /dev/null +++ b/test/files/invalid_user_clientkey_missing.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + name: example diff --git a/test/files/invalid_user_exec_apiversion_missing.yaml b/test/files/invalid_user_exec_apiversion_missing.yaml new file mode 100644 index 0000000..5332cc8 --- /dev/null +++ b/test/files/invalid_user_exec_apiversion_missing.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + exec: + args: + - "arg1" + - "arg2" + command: example-plugin + env: + - name: "foo" + value: "bar" + interactiveMode: IfAvailable + provideClusterInfo: false + name: example diff --git a/test/files/invalid_user_exec_command_missing.yaml b/test/files/invalid_user_exec_command_missing.yaml new file mode 100644 index 0000000..b13a468 --- /dev/null +++ b/test/files/invalid_user_exec_command_missing.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - "arg1" + - "arg2" + env: + - name: "foo" + value: "bar" + interactiveMode: IfAvailable + provideClusterInfo: false + name: example diff --git a/test/files/invalid_user_exec_envname_missing.yaml b/test/files/invalid_user_exec_envname_missing.yaml new file mode 100644 index 0000000..960fab3 --- /dev/null +++ b/test/files/invalid_user_exec_envname_missing.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - "arg1" + - "arg2" + command: example-plugin + env: + - value: "bar" + interactiveMode: IfAvailable + provideClusterInfo: false + name: example diff --git a/test/files/invalid_user_exec_interactivemode_missing.yaml b/test/files/invalid_user_exec_interactivemode_missing.yaml new file mode 100644 index 0000000..8609723 --- /dev/null +++ b/test/files/invalid_user_exec_interactivemode_missing.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - "arg1" + - "arg2" + command: example-plugin + env: + - name: "foo" + value: "bar" + provideClusterInfo: false + name: example diff --git a/test/files/invalid_user_impersonating.yaml b/test/files/invalid_user_impersonating.yaml new file mode 100644 index 0000000..40ea4ef --- /dev/null +++ b/test/files/invalid_user_impersonating.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + as-groups: + - system:masters + name: example diff --git a/test/files/invalid_user_multi_auth.yaml b/test/files/invalid_user_multi_auth.yaml new file mode 100644 index 0000000..49a2122 --- /dev/null +++ b/test/files/invalid_user_multi_auth.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + username: admin + password: secret + token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + name: example diff --git a/test/files/invalid_users_duplicate.yaml b/test/files/invalid_users_duplicate.yaml new file mode 100644 index 0000000..afa6f16 --- /dev/null +++ b/test/files/invalid_users_duplicate.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example + - user: + username: admin + password: secret + name: example diff --git a/test/files/invalid_users_name.yaml b/test/files/invalid_users_name.yaml new file mode 100644 index 0000000..313a999 --- /dev/null +++ b/test/files/invalid_users_name.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K diff --git a/test/files/invalid_users_required.yaml b/test/files/invalid_users_required.yaml new file mode 100644 index 0000000..95481fa --- /dev/null +++ b/test/files/invalid_users_required.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} diff --git a/test/files/invalid_users_user.yaml b/test/files/invalid_users_user.yaml new file mode 100644 index 0000000..078331e --- /dev/null +++ b/test/files/invalid_users_user.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - name: example diff --git a/test/files/token.txt b/test/files/token.txt new file mode 100644 index 0000000..b19a883 --- /dev/null +++ b/test/files/token.txt @@ -0,0 +1 @@ +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c diff --git a/test/files/valid.json b/test/files/valid.json new file mode 100644 index 0000000..5e2a77f --- /dev/null +++ b/test/files/valid.json @@ -0,0 +1,33 @@ +{ + "apiVersion": "v1", + "clusters": [ + { + "cluster": { + "certificate-authority-data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "server": "https://127.0.0.1:6443" + }, + "name": "example" + } + ], + "contexts": [ + { + "context": { + "cluster": "example", + "user": "example" + }, + "name": "example" + } + ], + "current-context": "example", + "kind": "Config", + "preferences": {}, + "users": [ + { + "user": { + "client-certificate-data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "client-key-data": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K" + }, + "name": "example" + } + ] +} \ No newline at end of file diff --git a/test/files/valid.yaml b/test/files/valid.yaml new file mode 100644 index 0000000..6dfbc3f --- /dev/null +++ b/test/files/valid.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:6443 + name: example +contexts: + - context: + cluster: example + user: example + name: example +current-context: example +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: example diff --git a/test/files/valid_multi.json b/test/files/valid_multi.json new file mode 100644 index 0000000..e56dcf4 --- /dev/null +++ b/test/files/valid_multi.json @@ -0,0 +1,253 @@ +{ + "apiVersion": "v1", + "clusters": [ + { + "cluster": { + "insecure-skip-tls-verify": true, + "server": "https://127.0.0.1:6443" + }, + "name": "cluster1" + }, + { + "cluster": { + "certificate-authority-data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "proxy-url": "http://user:password@proxy:5000", + "server": "https://10.0.100.1:6443" + }, + "name": "cluster2" + }, + { + "cluster": { + "certificate-authority": "test/files/cert/ca.crt", + "server": "https://55.55.55.55:6443" + }, + "name": "cluster3" + }, + { + "cluster": { + "certificate-authority-data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "server": "https://example.fake.eks.amazonaws.com:443" + }, + "name": "cluster4" + }, + { + "cluster": { + "disable-compression": true, + "insecure-skip-tls-verify": true, + "server": "https://kubernetes.docker.internal:6443" + }, + "name": "cluster5" + }, + { + "cluster": { + "certificate-authority": "test/files/cert/ca.crt", + "tls-server-name": "kubernetes.127.0.0.1", + "server": "https://0.0.0.0:60251" + }, + "name": "cluster6" + }, + { + "cluster": { + "certificate-authority": "test/files/cert/ca.crt", + "proxy-url": "http://user:password@proxy:5000", + "server": "https://openshift.fake.example.com:6443" + }, + "name": "cluster7" + }, + { + "cluster": { + "certificate-authority-data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "server": "https://example.fake.azmk8s.io:443" + }, + "name": "cluster8" + }, + { + "cluster": { + "insecure-skip-tls-verify": true, + "tls-server-name": "kubernetes.172.30.0.1", + "server": "https://172.30.0.1:9443" + }, + "name": "cluster9" + } + ], + "contexts": [ + { + "context": { + "cluster": "cluster1", + "user": "user1", + "namespace": "default" + }, + "name": "context1" + }, + { + "context": { + "cluster": "cluster2", + "user": "user2" + }, + "name": "context2" + }, + { + "context": { + "cluster": "cluster3", + "user": "user3" + }, + "name": "context3" + }, + { + "context": { + "cluster": "cluster4", + "user": "user4" + }, + "name": "context4" + }, + { + "context": { + "cluster": "cluster5", + "user": "user5", + "namespace": "kube-system" + }, + "name": "context5" + }, + { + "context": { + "cluster": "cluster6", + "user": "user6" + }, + "name": "context6" + }, + { + "context": { + "cluster": "cluster7", + "user": "user7" + }, + "name": "context7" + }, + { + "context": { + "cluster": "cluster8", + "user": "user8" + }, + "name": "context8" + }, + { + "context": { + "cluster": "cluster9", + "user": "user9" + }, + "name": "context9" + } + ], + "current-context": "context1", + "kind": "Config", + "preferences": {}, + "users": [ + { + "user": { + "client-certificate-data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "client-key-data": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K" + }, + "name": "user1" + }, + { + "user": { + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + }, + "name": "user2" + }, + { + "user": { + "client-certificate": "test/files/cert/example.crt", + "client-key": "test/files/cert/example.key" + }, + "name": "user3" + }, + { + "user": { + "exec": { + "apiVersion": "client.authentication.k8s.io/v1beta1", + "args": [ + "--region", + "us-east-1", + "eks", + "get-token", + "--cluster-name", + "example" + ], + "command": "aws", + "env": null, + "interactiveMode": "IfAvailable", + "provideClusterInfo": false + } + }, + "name": "user4" + }, + { + "user": { + "username": "admin", + "password": "secret" + }, + "name": "user5" + }, + { + "user": { + "auth-provider": { + "config": { + "client-id": "kubernetes", + "client-secret": "1db158f6-177d-4d9c-8a8b-d36869918ec5", + "id-token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", + "idp-certificate-authority": "test/files/cert/example.crt", + "idp-issuer-url": "https://idp.example.com:8443/oidc", + "refresh-token": "q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXq" + } + } + }, + "name": "user6" + }, + { + "user": { + "tokenFile": "token.txt", + "as": "admin", + "as-uid": "uid123", + "as-groups": [ + "system:masters" + ], + "as-user-extra": { + "reason": [ + "istioctl" + ] + } + }, + "name": "user7" + }, + { + "user": { + "client-certificate-data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "client-key-data": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K", + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + }, + "name": "user8" + }, + { + "user": { + "exec": { + "apiVersion": "client.authentication.k8s.io/v1beta1", + "args": [ + "arg1", + "arg2" + ], + "command": "example-plugin", + "env": [ + { + "name": "foo", + "value": "bar" + } + ], + "installHint": "example-plugin is required to authenticate to the current cluster. It can be installed:\nOn macOS: brew install example-plugin\nOn Ubuntu: apt-get install example-plugin\nOn Fedora: dnf install example-plugin\n", + "interactiveMode": "IfAvailable", + "provideClusterInfo": false + } + }, + "name": "user9" + } + ] +} diff --git a/test/files/valid_multi.yaml b/test/files/valid_multi.yaml new file mode 100644 index 0000000..1c4dba8 --- /dev/null +++ b/test/files/valid_multi.yaml @@ -0,0 +1,159 @@ +apiVersion: v1 +clusters: + - cluster: + insecure-skip-tls-verify: true + server: https://127.0.0.1:6443 + name: cluster1 + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + proxy-url: http://user:password@proxy:5000 + server: https://10.0.100.1:6443 + name: cluster2 + - cluster: + certificate-authority: test/files/cert/ca.crt + server: https://55.55.55.55:6443 + name: cluster3 + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://example.fake.eks.amazonaws.com:443 + name: cluster4 + - cluster: + disable-compression: true + insecure-skip-tls-verify: true + server: https://kubernetes.docker.internal:6443 + name: cluster5 + - cluster: + certificate-authority: test/files/cert/ca.crt + tls-server-name: kubernetes.127.0.0.1 + server: https://0.0.0.0:60251 + name: cluster6 + - cluster: + certificate-authority: test/files/cert/ca.crt + proxy-url: http://user:password@proxy:5000 + server: https://openshift.fake.example.com:6443 + name: cluster7 + - cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://example.fake.azmk8s.io:443 + name: cluster8 + - cluster: + insecure-skip-tls-verify: true + tls-server-name: kubernetes.172.30.0.1 + server: https://172.30.0.1:9443 + name: cluster9 +contexts: + - context: + cluster: cluster1 + user: user1 + namespace: default + name: context1 + - context: + cluster: cluster2 + user: user2 + name: context2 + - context: + cluster: cluster3 + user: user3 + name: context3 + - context: + cluster: cluster4 + user: user4 + name: context4 + - context: + cluster: cluster5 + user: user5 + namespace: kube-system + name: context5 + - context: + cluster: cluster6 + user: user6 + name: context6 + - context: + cluster: cluster7 + user: user7 + name: context7 + - context: + cluster: cluster8 + user: user8 + name: context8 + - context: + cluster: cluster9 + user: user9 + name: context9 +current-context: context1 +kind: Config +preferences: {} +users: + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + name: user1 + - user: + token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + name: user2 + - user: + client-certificate: test/files/cert/example.crt + client-key: test/files/cert/example.key + name: user3 + - user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - --region + - us-east-1 + - eks + - get-token + - --cluster-name + - example + command: aws + env: null + interactiveMode: IfAvailable + provideClusterInfo: false + name: user4 + - user: + username: admin + password: secret + name: user5 + - user: + auth-provider: + config: + client-id: kubernetes + client-secret: 1db158f6-177d-4d9c-8a8b-d36869918ec5 + id-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + idp-certificate-authority: test/files/cert/example.crt + idp-issuer-url: https://idp.example.com:8443/oidc + refresh-token: q1bKLFOyUiosTfawzA93TzZIDzH2TNa2SMm0zEiPKTUwME6BkEo6Sql5yUWVBSWpKUGphaWpxSVAfekBOZbBhaEW+VlFUeVRGcluyVF5JT4+haZmPsluFoFu5XkpXk5BXq + name: user6 + - user: + tokenFile: token.txt + as: admin + as-uid: uid123 + as-groups: + - system:masters + as-user-extra: + reason: + - istioctl + name: user7 + - user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRRENDQWlnQ0NRRHhVdFR5cHhSeDBUQU5CZ2txaGtpRzl3MEJBUXNGQURCaU1Rc3dDUVlEVlFRR0V3SlYKVXpFTk1Bc0dBMVVFQ0F3RVUzUjBaVEVOTUFzR0ExVUVCd3dFUTJsMGVURVFNQTRHQTFVRUNnd0hSWGhoYlhCcwpaVEVMTUFrR0ExVUVDd3dDU1ZReEZqQVVCZ05WQkFNTURTb3VaWGhoYlhCc1pTNWpiMjB3SGhjTk1qTXdNakl4Ck1EZ3hNREkyV2hjTk16TXdNakU0TURneE1ESTJXakJpTVFzd0NRWURWUVFHRXdKVlV6RU5NQXNHQTFVRUNBd0UKVTNSMFpURU5NQXNHQTFVRUJ3d0VRMmwwZVRFUU1BNEdBMVVFQ2d3SFJYaGhiWEJzWlRFTE1Ba0dBMVVFQ3d3QwpTVlF4RmpBVUJnTlZCQU1NRFNvdVpYaGhiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ3R4RlU4VGhXaTFZVGtTQ1hmVDg3eUFUMEVXVWlSa3dZaHFQOGZ0amRPc3BNZDBiQWwKZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHamY3NHRPdUtSVWl5N2JacjNFL0tzaFIyMG9KZnVjWTNmRFlyRApQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvZGt1bzFsVUU0Nm0rTTcxYUFPWFJLemVDbjVXUXlSYUpsclcvCm1WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVdHZGZudDhVVXZ0Y0F5WGNGWkZmeTVvcWhUYWNSYlAwRmZBSFIKeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncGpXTXV4U2dxeHNRUU1RaHNKTk1teVMrN2RqVlJnRUdTV243YQp6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRIdnhnMEFhdEZBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFECmdnRUJBQ3FYMlgrMkFTMXhFTTE2SDJIc0RHVXpkK2pVRzlwS054ODdnZ3Yvdml0a2JXVVZ5QkN1bEVVa0VEUkIKWmJ3OTJZcU13NHkvY25tQlk0ZG1mdXVzT1BRSnpybmk5VjVqa2Z3TFU1cXFnU3ZNUzdWSFRXMlZINkFiQWk1bwo1aWhYeFU2dVN3VWQwWjFaS1lPQmdkU3QwVVFIZGt1OWFNRGw0cVEyT2xqZndyRE41eEVuZ0k0ckJ1UmpSZ1J2CmtJcDdaeG90MUtBbjUvRm15ME9TSEpYVCt5VkdiYUtNRGZ2YjZCb3VYdTAyd1VPV1c4cmlwLyt0NENtWENUMXYKUWoyWGtRTGZkUG9lVUE0SXdaZlk0dmU2Y2U0eW9BTGJubThKWlRrcXBqOXZkNENObWt5VVYrNHVXQ3FWZCswQgpRSVR1MHlMOHRYRFVrL2w5VnZ3bUhZY2E4WjA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ3R4RlU4VGhXaTFZVGsKU0NYZlQ4N3lBVDBFV1VpUmt3WWhxUDhmdGpkT3NwTWQwYkFsZmdRVmRXbTdQS01lV0V0VkpVTFZlUzg2NnFHagpmNzR0T3VLUlVpeTdiWnIzRS9Lc2hSMjBvSmZ1Y1kzZkRZckRQelBmVno2eEk1UE1INmJRTlY1UkxzMGxXc0hvCmRrdW8xbFVFNDZtK003MWFBT1hSS3plQ241V1F5UmFKbHJXL21WbkFOQWNBcjFjNDRNTElOcFR2T2diZ0R0bVcKR2RmbnQ4VVV2dGNBeVhjRlpGZnk1b3FoVGFjUmJQMEZmQUhSeEJBak5hcXRsek9TRC91UjVrcDF6NHJRcFNncApqV011eFNncXhzUVFNUWhzSk5NbXlTKzdkalZSZ0VHU1duN2F6UHJ1V3NPQkhvMGkwMWRDUUtqNVQ3Ynk0NXRICnZ4ZzBBYXRGQWdNQkFBRUNnZ0VBRzJrWEVQWTRUNEZpL3llcVlibVRLWFdzakYwUkozV0x5QStDZnh3ZFNWcTkKL2p3dmp4cDd4bTdKQ1BJZHdSR29nSHZxT1FadXZ0cDRPUFJUcVlyYVpwWVIzRmNEMU9uZW8vd3puV1NmMHNzeQoxL2FvNXZlM1ZRbk1KK0UyMVVKQTdDTWZCNnRjVFFJdUNGOXd1K2RqYmV3RHdLOGt0V2ZpMk1YNmNhNSt4MkhPClUrWHZQSEozUWxqb2U0ZHhYVHJ2N0ZtYlRGdnJpd2JuclBhM3VMWFU2d2lOMTZmMWwrQURROXUxTVZtdGExOFYKRzZHcDFmVXQ3VElTQTkycXNPRlhDUi9qVUpYb3ZJWGZUTjFycXZlcjZLYmRMVm5RQXhvSzV2L3UwNEpBZzJ3dwp4NWRqNC9CKzlYUDV0VDFCWjQwNmNFUlhsUUU2Y0xTMDRpMTcrdGFNZ1FLQmdRRGwvUzVrdFVTNWtpanN2R2hlCksxS0dDc2hRUER5NmRDVGdUeWRkUXppSzh1OXltVTVUT3k4dERPeWIvSms5bzRNQXF2R2VKbFNCaEEwcjRDV00KRFNNWFBqUjZFV3lyU3pGdHdHWUZJM3FXYjJtWS9GeFNTZXNMeHhhaWNQcGs1Y3BiaTZHc3RkNGtoK0VuSkoxMwowVU1Pd2RoUmtCYkRESmxncUdRNnZhTEVOUUtCZ1FEQmExMzhzQ2FzUG50Ymgvc3RDZUliRkhXb0RKbnpwYi9QClNFWlBSWjIraXhEa3VJOWRjVGdjWS9KSGQ0UDAwYkpPZituamdYWkxwenNpKzV3dTlaaW1kUm9PTUZxRklDZ0IKMjhubUNHOWxHZGNudEZINmdhazJWZmc5UlU1bDhxYkp3SmJDZ3JuRjNDQXdCSkphRnh0em1ncndhYjlIOG1VNwpHSWszc05rTTBRS0JnUURDZTExTzVnWXVrazB2RzRkNkVsSmZiU0RFMEp0ZDVEY0d3NGg3RWd2dlc4MWw4QVBPCjJCNWxqeWRLSk1tRTJROC9jazZOT01aL0d5WjBNc0F0ZFRKMlJqRGtCSFlMUjdPTnBvUGUxb2lrUzZSVkxSbjQKcis4bDczM1JjWTRiNGtGRE5vbEozaVR5YVVEWTg5cUE1cUU1Q215ZFZDWWJYRDBiQW1wM1RjTWsvUUtCZ0Z5Rwp0eXhsTytyVDdRRUpXTi9meFhrODNWZnB4MC9sNzQ4Q1BSZzQ3bEF6aUg1Ung4dGttUG9EMmVmVVJaeTlIN1lyCnZNQm5zeVpYdHBOeWwvRmk3WVpicUg0M0pXWmZ6cU9zOTdXQ1BYKzR6OU1ma01Qc2VQMFVQUzlhVXptenpaUGYKL0g3S09JSnRYang2UTJTemZ4OWJCbmFocjY2RVIyYnd3dHVRVHhTeEFvR0FPd3h5Tmg1R2YyNGYycDJKYk5BSAowSmVxbEp3QTQveFpPQ0pMVDdkcER2ZjRrVDNGUXNiQndDcHJRSVNlUG9sK282OTFMVGtxT0ZrbWRWejdqbnZOCkUzaCtMYUVIN2NHODEySTRkOTlGcjh4WGZHTVBOUUVGcVJvUDN2Vm1GMy9MSUlwLzNoNmlKbC9qMGxNQm5OdzgKbWhyY3ZCTW4vSnBLNDMweFZLNkxLYlk9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K + token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c + name: user8 + - user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + args: + - "arg1" + - "arg2" + command: example-plugin + env: + - name: "foo" + value: "bar" + installHint: | + example-plugin is required to authenticate to the current cluster. It can be installed: + On macOS: brew install example-plugin + On Ubuntu: apt-get install example-plugin + On Fedora: dnf install example-plugin + interactiveMode: IfAvailable + provideClusterInfo: false + name: user9 diff --git a/test/kubeconfig_merge_test.dart b/test/kubeconfig_merge_test.dart new file mode 100644 index 0000000..f6a3c54 --- /dev/null +++ b/test/kubeconfig_merge_test.dart @@ -0,0 +1,70 @@ +import 'dart:io'; + +import 'package:kubeconfig/kubeconfig.dart'; +import 'package:test/test.dart'; + +Future main() async { + Future getKubeconfig(String file) async { + final kubeconfigYaml = await File('test/files/$file').readAsString(); + final kubeconfig = Kubeconfig.fromYaml(kubeconfigYaml); + return kubeconfig; + } + + final kubeconfigValid1 = await getKubeconfig('valid.yaml'); + final kubeconfigValid2 = await getKubeconfig('valid_multi.yaml'); + final kubeconfigInvalid1 = + await getKubeconfig('invalid_cluster_certificate_both.yaml'); + final kubeconfigInvalid2 = + await getKubeconfig('invalid_user_multi_auth.yaml'); + + group('Kubeconfig merge()', () { + test('creates an instance with valid kubeconfig objects', () { + final kubeconfigMerged = kubeconfigValid1.merge(kubeconfigValid2); + expect(kubeconfigMerged, isNotNull); + expect(kubeconfigMerged!.contexts!.length, 10); + }); + + test('cannot merge with invalid kubeconfig objects', () { + final kubeconfigNotMerged = kubeconfigInvalid1.merge(kubeconfigInvalid2); + expect(kubeconfigNotMerged, isNull); + }); + + test('throws an exception with an invalid source kubeconfig object', () { + expect( + () => kubeconfigInvalid1.merge( + kubeconfigValid1, + throwExceptions: true, + ), + throwsA(isA()), + ); + }); + + test('throws an exception with an invalid target kubeconfig object', () { + expect( + () => kubeconfigValid1.merge( + kubeconfigInvalid1, + throwExceptions: true, + ), + throwsA(isA()), + ); + }); + + test('throws an exception with invalid kubeconfig objects', () { + expect( + () => kubeconfigInvalid1.merge( + kubeconfigInvalid2, + throwExceptions: true, + ), + throwsA(isA()), + ); + }); + + test('preserves current context', () { + final kubeconfigMerged = kubeconfigValid1.merge( + kubeconfigValid2, + preserveCurrentContext: true, + ); + expect(kubeconfigMerged!.currentContext, kubeconfigValid1.currentContext); + }); + }); +} diff --git a/test/kubeconfig_test.dart b/test/kubeconfig_test.dart new file mode 100644 index 0000000..3d90555 --- /dev/null +++ b/test/kubeconfig_test.dart @@ -0,0 +1,466 @@ +import 'dart:convert'; + +import 'package:kubeconfig/kubeconfig.dart'; +import 'package:test/test.dart'; + +void main() { + group('Kubeconfig', () { + const authProviderConfig = AuthProviderConfig( + name: 'name', + config: {'key': 'value'}, + ); + const execEnv = ExecEnv( + name: 'name', + value: 'value', + ); + const exec = Exec( + command: 'command', + apiVersion: 'client.authentication.k8s.io/v1', + interactiveMode: InteractiveMode.IfAvailable, + args: ['arg'], + env: [execEnv], + installHint: 'installHint line1\ninstallHint line2', + provideClusterInfo: false, + ); + const authInfo = AuthInfo( + authProvider: authProviderConfig, + clientCertificate: 'certificate-file-path', + clientCertificateData: 'certificate-data', + clientKey: 'client-key-file-path', + clientKeyData: 'client-key-data', + exec: exec, + impersonate: 'impersonate', + impersonateGroups: ['impersonate-group'], + impersonateUID: 'impersonate-uid', + impersonateUserExtra: { + 'key': ['value'], + }, + password: 'password', + token: 'token', + tokenFile: 'token-file-path', + username: 'username', + ); + const cluster = Cluster( + certificateAuthority: 'certificate-authority-file-path', + certificateAuthorityData: 'certificate-authority-data', + disableCompression: false, + insecureSkipTlsVerify: false, + proxyURL: 'proxy-url', + server: 'server', + tlsServerName: 'tls-server-name', + ); + const context = Context( + cluster: 'cluster', + authInfo: 'user', + namespace: 'namespace', + ); + const namedAuthInfo = NamedAuthInfo( + name: 'name', + user: authInfo, + ); + const namedCluster = NamedCluster( + name: 'name', + cluster: cluster, + ); + const namedContext = NamedContext( + name: 'name', + context: context, + ); + const preferences = Preferences( + colors: true, + ); + const kubeconfig = Kubeconfig( + apiVersion: 'v1', + authInfos: [namedAuthInfo], + clusters: [namedCluster], + contexts: [namedContext], + currentContext: 'example', + kind: 'Config', + preferences: preferences, + ); + + test('can be instantiated and all props are valid', () { + expect(authProviderConfig, isNotNull); + expect(authProviderConfig.props, isNotNull); + expect(authProviderConfig.toString(), isNotNull); + + expect(execEnv, isNotNull); + expect(execEnv.props, isNotNull); + expect(execEnv.toString(), isNotNull); + + expect(exec, isNotNull); + expect(exec.props, isNotNull); + expect(exec.toString(), isNotNull); + + expect(authInfo, isNotNull); + expect(authInfo.props, isNotNull); + expect(authInfo.toString(), isNotNull); + + expect(cluster, isNotNull); + expect(cluster.props, isNotNull); + expect(cluster.toString(), isNotNull); + + expect(context, isNotNull); + expect(context.props, isNotNull); + expect(context.toString(), isNotNull); + + expect(namedAuthInfo, isNotNull); + expect(namedAuthInfo.props, isNotNull); + expect(namedAuthInfo.toString(), isNotNull); + + expect(namedCluster, isNotNull); + expect(namedCluster.props, isNotNull); + expect(namedCluster.toString(), isNotNull); + + expect(namedContext, isNotNull); + expect(namedContext.props, isNotNull); + expect(namedContext.toString(), isNotNull); + + expect(preferences, isNotNull); + expect(preferences.props, isNotNull); + expect(preferences.toString(), isNotNull); + + expect(kubeconfig, isNotNull); + expect(kubeconfig.props, isNotNull); + expect(kubeconfig.toString(), isNotNull); + }); + + test('can be instantiated with null or default values', () { + const kubeconfig = + Kubeconfig(authInfos: null, clusters: null, contexts: null); + expect(kubeconfig, isNotNull); + }); + + group('json', () { + final kubeconfigJson = json.encode(kubeconfig.toJson()); + + test('toJson() converts a kubeconfig object to json', () { + expect(kubeconfigJson, isNotNull); + }); + + test('fromJson() creates an instance with a valid yaml', () { + final kubeconfigFromJson = Kubeconfig.fromJson( + json.decode(kubeconfigJson) as Map, + ); + expect(kubeconfigFromJson, isNotNull); + }); + }); + + group('yaml', () { + final kubeconfigYaml = kubeconfig.toYaml(); + + test('toYaml() converts a kubeconfig object to yaml', () { + expect(kubeconfigYaml, isNotNull); + }); + + test('fromYaml() throws YamlException if the yaml is empty', () { + expect( + () => Kubeconfig.fromYaml(''), + throwsA(isA()), + ); + }); + + test('fromYaml() throws YamlException if the yaml is not valid', () { + expect( + () => Kubeconfig.fromYaml('`invalid`'), + throwsA(isA()), + ); + }); + + test('fromYaml() creates an instance with a valid yaml', () { + final kubeconfig = Kubeconfig.fromYaml(kubeconfigYaml); + expect(kubeconfig, isNotNull); + }); + }); + + group('ValidationResult', () { + const validationResult = ValidationResult( + code: ValidationCode.valid, + description: 'description', + ); + final validationResultJson = json.encode(validationResult.toJson()); + final validationResultCopy = validationResult.copyWith( + code: ValidationCode.contextsRequired, + description: 'description2', + ); + final validationResultClone = validationResult.copyWith(); + final validationResultCopyWithCode = + validationResult.copyWith.code(ValidationCode.contextsRequired); + final validationResultCopyWithDescription = + validationResult.copyWith.description('description2'); + + test('can be instantiated and all props are valid', () { + expect(validationResult, isNotNull); + expect(validationResult.props, isNotNull); + expect(validationResult.toString(), isNotNull); + }); + + test('can be converted to json with Kubeconfig.toJson()', () { + expect(validationResultJson, isNotNull); + }); + + test('can be instantiated with ValidationResult.fromJson()', () { + final validationResultFromJson = ValidationResult.fromJson( + json.decode(validationResultJson) as Map, + ); + expect(validationResultFromJson, isNotNull); + }); + + test('can be instantiated with copyWith()', () { + expect(validationResultCopy, isNotNull); + expect(validationResultClone, isNotNull); + expect(validationResultCopyWithCode, isNotNull); + expect(validationResultCopyWithDescription, isNotNull); + }); + }); + + group('copyWith', () { + final authProviderConfigCopy = authProviderConfig.copyWith( + name: 'name2', + config: {'key2': 'value2'}, + ); + final execEnvCopy = execEnv.copyWith( + name: 'name2', + value: 'value2', + ); + final execCopy = exec.copyWith( + command: 'command2', + apiVersion: 'client.authentication.k8s.io/v1beta1', + interactiveMode: InteractiveMode.Never, + args: ['arg2'], + env: [execEnvCopy], + installHint: 'installHint2 line1\ninstallHint2 line2', + provideClusterInfo: false, + ); + final authInfoCopy = authInfo.copyWith( + authProvider: authProviderConfigCopy, + clientCertificate: 'certificate-file-path2', + clientCertificateData: 'certificate-data2', + clientKey: 'client-key-file-path2', + clientKeyData: 'client-key-data2', + exec: execCopy, + impersonate: 'impersonate2', + impersonateGroups: ['impersonate-group2'], + impersonateUID: 'impersonate-uid2', + impersonateUserExtra: { + 'key2': ['value2'], + }, + password: 'password2', + token: 'token2', + tokenFile: 'token-file-path2', + username: 'username2', + ); + final clusterCopy = cluster.copyWith( + certificateAuthority: 'certificate-authority-file-path2', + certificateAuthorityData: 'certificate-authority-data2', + disableCompression: false, + insecureSkipTlsVerify: false, + proxyURL: 'proxy-url2', + server: 'server2', + tlsServerName: 'tls-server-name2', + ); + final contextCopy = context.copyWith( + cluster: 'cluster2', + authInfo: 'user2', + namespace: 'namespace2', + ); + final namedAuthInfoCopy = namedAuthInfo.copyWith( + name: 'name2', + user: authInfoCopy, + ); + final namedClusterCopy = namedCluster.copyWith( + name: 'name2', + cluster: clusterCopy, + ); + final namedContextCopy = namedContext.copyWith( + name: 'name2', + context: contextCopy, + ); + final preferencesCopy = preferences.copyWith( + colors: false, + ); + final kubeconfigCopy = kubeconfig.copyWith( + apiVersion: 'v1', + authInfos: [namedAuthInfoCopy], + clusters: [namedClusterCopy], + contexts: [namedContextCopy], + currentContext: 'example2', + kind: 'Config', + preferences: preferencesCopy, + ); + + final authProviderConfigClone = authProviderConfig.copyWith(); + final execEnvClone = execEnv.copyWith(); + final execClone = exec.copyWith(); + final authInfoClone = authInfo.copyWith(); + final clusterClone = cluster.copyWith(); + final contextClone = context.copyWith(); + final namedAuthInfoClone = namedAuthInfo.copyWith(); + final namedClusterClone = namedCluster.copyWith(); + final namedContextClone = namedContext.copyWith(); + final preferencesClone = preferences.copyWith(); + final kubeconfigClone = kubeconfig.copyWith(); + + final authProviderConfigCopyWithName = + authProviderConfig.copyWith.name('name2'); + final authProviderConfigCopyWithConfig = + authProviderConfig.copyWith.config({'key2': 'value2'}); + final execEnvCopyWithName = execEnv.copyWith.name('name2'); + final execEnvCopyWithValue = execEnv.copyWith.value('value2'); + final execCopyWithCommand = exec.copyWith.command('command2'); + final execCopyWithApiVersion = + exec.copyWith.apiVersion('client.authentication.k8s.io/v1beta1'); + final execCopyWithInteractiveMode = + exec.copyWith.interactiveMode(InteractiveMode.Never); + final execCopyWithArgs = exec.copyWith.args(['arg2']); + final execCopyWithEnv = exec.copyWith.env([execEnvCopy]); + final execCopyWithInstallHint = + exec.copyWith.installHint('installHint2 line1\ninstallHint2 line2'); + final execCopyWithProvideClusterInfo = + exec.copyWith.provideClusterInfo(false); + final authInfoCopyWithAuthProvider = + authInfo.copyWith.authProvider(authProviderConfigCopy); + final authInfoCopyWithClientCertificate = + authInfo.copyWith.clientCertificate('certificate-file-path2'); + final authInfoCopyWithClientCertificateData = + authInfo.copyWith.clientCertificateData('certificate-data2'); + final authInfoCopyWithClientKey = + authInfo.copyWith.clientKey('client-key-file-path2'); + final authInfoCopyWithClientKeyData = + authInfo.copyWith.clientKeyData('client-key-data2'); + final authInfoCopyWithExec = authInfo.copyWith.exec(execCopy); + final authInfoCopyWithImpersonate = + authInfo.copyWith.impersonate('impersonate2'); + final authInfoCopyWithImpersonateGroups = + authInfo.copyWith.impersonateGroups(['impersonate-group2']); + final authInfoCopyWithImpersonateUID = + authInfo.copyWith.impersonateUID('impersonate-uid2'); + final authInfoCopyWithImpersonateUserExtra = + authInfo.copyWith.impersonateUserExtra({ + 'key2': ['value2'], + }); + final authInfoCopyWithPassword = authInfo.copyWith.password('password2'); + final authInfoCopyWithToken = authInfo.copyWith.token('token2'); + final authInfoCopyWithTokenFile = + authInfo.copyWith.tokenFile('token-file-path2'); + final authInfoCopyWithUsername = authInfo.copyWith.username('username2'); + final clusterCopyWithCertificateAuthority = cluster.copyWith + .certificateAuthority('certificate-authority-file-path2'); + final clusterCopyWithCertificateAuthorityData = cluster.copyWith + .certificateAuthorityData('certificate-authority-data2'); + final clusterCopyWithDisableCompression = + cluster.copyWith.disableCompression(false); + final clusterCopyWithInsecureSkipTlsVerify = + cluster.copyWith.insecureSkipTlsVerify(false); + final clusterCopyWithProxyURL = cluster.copyWith.proxyURL('proxy-url2'); + final clusterCopyWithServer = cluster.copyWith.server('server2'); + final clusterCopyWithTlsServerName = + cluster.copyWith.tlsServerName('tls-server-name2'); + final contextCopyWithCluster = context.copyWith.cluster('cluster2'); + final contextCopyWithAuthInfo = context.copyWith.authInfo('user2'); + final contextCopyWithNamespace = context.copyWith.namespace('namespace2'); + final namedAuthInfoCopyWithName = namedAuthInfo.copyWith.name('name2'); + final namedAuthInfoCopyWithUser = + namedAuthInfo.copyWith.user(authInfoCopy); + final namedClusterCopyWithName = namedCluster.copyWith.name('name2'); + final namedClusterCopyWithCluster = + namedCluster.copyWith.cluster(clusterCopy); + final namedContextCopyWithName = namedContext.copyWith.name('name2'); + final namedContextCopyWithContext = + namedContext.copyWith.context(contextCopy); + final preferencesCopyWithColors = preferences.copyWith.colors(false); + final kubeconfigCopyWithApiVersion = kubeconfig.copyWith.apiVersion('v1'); + final kubeconfigCopyWithAuthInfos = + kubeconfig.copyWith.authInfos([namedAuthInfoCopy]); + final kubeconfigCopyWithClusters = + kubeconfig.copyWith.clusters([namedClusterCopy]); + final kubeconfigCopyWithContexts = + kubeconfig.copyWith.contexts([namedContextCopy]); + final kubeconfigCopyWithCurrentContext = + kubeconfig.copyWith.currentContext('example2'); + final kubeconfigCopyWithKind = kubeconfig.copyWith.kind('Config'); + final kubeconfigCopyWithPreferences = + kubeconfig.copyWith.preferences(preferencesCopy); + + test('creates a new copy object', () { + expect(authProviderConfigCopy, isNotNull); + expect(execEnvCopy, isNotNull); + expect(execCopy, isNotNull); + expect(authInfoCopy, isNotNull); + expect(clusterCopy, isNotNull); + expect(contextCopy, isNotNull); + expect(namedAuthInfoCopy, isNotNull); + expect(namedClusterCopy, isNotNull); + expect(namedContextCopy, isNotNull); + expect(preferencesCopy, isNotNull); + expect(kubeconfigCopy, isNotNull); + }); + + test('creates a clone object', () { + expect(authProviderConfigClone, isNotNull); + expect(execEnvClone, isNotNull); + expect(execClone, isNotNull); + expect(authInfoClone, isNotNull); + expect(clusterClone, isNotNull); + expect(contextClone, isNotNull); + expect(namedAuthInfoClone, isNotNull); + expect(namedClusterClone, isNotNull); + expect(namedContextClone, isNotNull); + expect(preferencesClone, isNotNull); + expect(kubeconfigClone, isNotNull); + }); + + test('creates a new copy object with the specified fields', () { + expect(authProviderConfigCopyWithName, isNotNull); + expect(authProviderConfigCopyWithConfig, isNotNull); + expect(execEnvCopyWithName, isNotNull); + expect(execEnvCopyWithValue, isNotNull); + expect(execCopyWithCommand, isNotNull); + expect(execCopyWithApiVersion, isNotNull); + expect(execCopyWithInteractiveMode, isNotNull); + expect(execCopyWithArgs, isNotNull); + expect(execCopyWithEnv, isNotNull); + expect(execCopyWithInstallHint, isNotNull); + expect(execCopyWithProvideClusterInfo, isNotNull); + expect(authInfoCopyWithAuthProvider, isNotNull); + expect(authInfoCopyWithClientCertificate, isNotNull); + expect(authInfoCopyWithClientCertificateData, isNotNull); + expect(authInfoCopyWithClientKey, isNotNull); + expect(authInfoCopyWithClientKeyData, isNotNull); + expect(authInfoCopyWithExec, isNotNull); + expect(authInfoCopyWithImpersonate, isNotNull); + expect(authInfoCopyWithImpersonateGroups, isNotNull); + expect(authInfoCopyWithImpersonateUID, isNotNull); + expect(authInfoCopyWithImpersonateUserExtra, isNotNull); + expect(authInfoCopyWithPassword, isNotNull); + expect(authInfoCopyWithToken, isNotNull); + expect(authInfoCopyWithTokenFile, isNotNull); + expect(authInfoCopyWithUsername, isNotNull); + expect(clusterCopyWithCertificateAuthority, isNotNull); + expect(clusterCopyWithCertificateAuthorityData, isNotNull); + expect(clusterCopyWithDisableCompression, isNotNull); + expect(clusterCopyWithInsecureSkipTlsVerify, isNotNull); + expect(clusterCopyWithProxyURL, isNotNull); + expect(clusterCopyWithServer, isNotNull); + expect(clusterCopyWithTlsServerName, isNotNull); + expect(contextCopyWithCluster, isNotNull); + expect(contextCopyWithAuthInfo, isNotNull); + expect(contextCopyWithNamespace, isNotNull); + expect(namedAuthInfoCopyWithName, isNotNull); + expect(namedAuthInfoCopyWithUser, isNotNull); + expect(namedClusterCopyWithName, isNotNull); + expect(namedClusterCopyWithCluster, isNotNull); + expect(namedContextCopyWithName, isNotNull); + expect(namedContextCopyWithContext, isNotNull); + expect(preferencesCopyWithColors, isNotNull); + expect(kubeconfigCopyWithApiVersion, isNotNull); + expect(kubeconfigCopyWithAuthInfos, isNotNull); + expect(kubeconfigCopyWithClusters, isNotNull); + expect(kubeconfigCopyWithContexts, isNotNull); + expect(kubeconfigCopyWithCurrentContext, isNotNull); + expect(kubeconfigCopyWithKind, isNotNull); + expect(kubeconfigCopyWithPreferences, isNotNull); + }); + }); + }); +} diff --git a/test/kubeconfig_validation_test.dart b/test/kubeconfig_validation_test.dart new file mode 100644 index 0000000..ed9b406 --- /dev/null +++ b/test/kubeconfig_validation_test.dart @@ -0,0 +1,446 @@ +import 'dart:io'; + +import 'package:kubeconfig/kubeconfig.dart'; +import 'package:test/test.dart'; + +void main() { + group('ValidationCode', () { + Future getKubeconfig(String file) async { + final kubeconfigYaml = await File('test/files/$file').readAsString(); + final kubeconfig = Kubeconfig.fromYaml(kubeconfigYaml); + return kubeconfig; + } + + test('valid (single)', () async { + final result = (await getKubeconfig('valid.yaml')).validate(); + expect(result.code, ValidationCode.valid); + }); + + test('valid (multi)', () async { + final kubeconfig = await getKubeconfig('valid_multi.yaml'); + final result = kubeconfig.validate(); + expect(result.code, ValidationCode.valid); + expect(kubeconfig.contexts, isNotNull); + expect(kubeconfig.contexts!.length, 9); + }); + + test('clustersRequired', () async { + final result = + (await getKubeconfig('invalid_clusters_required.yaml')).validate(); + expect(result.code, ValidationCode.clustersRequired); + expect( + () async => (await getKubeconfig('invalid_clusters_required.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('contextsRequired', () async { + final result = + (await getKubeconfig('invalid_contexts_required.yaml')).validate(); + expect(result.code, ValidationCode.contextsRequired); + expect( + () async => (await getKubeconfig('invalid_contexts_required.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('usersRequired', () async { + final result = + (await getKubeconfig('invalid_users_required.yaml')).validate(); + expect(result.code, ValidationCode.usersRequired); + expect( + () async => (await getKubeconfig('invalid_users_required.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('nameRequiredForNamedCluster', () async { + final result = + (await getKubeconfig('invalid_clusters_name.yaml')).validate(); + expect(result.code, ValidationCode.nameRequiredForNamedCluster); + expect( + () async => (await getKubeconfig('invalid_clusters_name.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('nameRequiredForNamedContext', () async { + final result = + (await getKubeconfig('invalid_contexts_name.yaml')).validate(); + expect(result.code, ValidationCode.nameRequiredForNamedContext); + expect( + () async => (await getKubeconfig('invalid_contexts_name.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('nameRequiredForNamedUsers', () async { + final result = + (await getKubeconfig('invalid_users_name.yaml')).validate(); + expect(result.code, ValidationCode.nameRequiredForNamedUser); + expect( + () async => (await getKubeconfig('invalid_users_name.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clusterRequiredForNamedCluster', () async { + final result = + (await getKubeconfig('invalid_clusters_cluster.yaml')).validate(); + expect(result.code, ValidationCode.clusterRequiredForNamedCluster); + expect( + () async => (await getKubeconfig('invalid_clusters_cluster.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('contextRequiredForNamedContext', () async { + final result = + (await getKubeconfig('invalid_contexts_context.yaml')).validate(); + expect(result.code, ValidationCode.contextRequiredForNamedContext); + expect( + () async => (await getKubeconfig('invalid_contexts_context.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('userRequiredForNamedUsers', () async { + final result = + (await getKubeconfig('invalid_users_user.yaml')).validate(); + expect(result.code, ValidationCode.userRequiredForNamedUser); + expect( + () async => (await getKubeconfig('invalid_users_user.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('serverRequiredForCluster', () async { + final result = + (await getKubeconfig('invalid_cluster_server.yaml')).validate(); + expect(result.code, ValidationCode.serverRequiredForCluster); + expect( + () async => (await getKubeconfig('invalid_cluster_server.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clusterRequiredForContext', () async { + final result = + (await getKubeconfig('invalid_context_cluster.yaml')).validate(); + expect(result.code, ValidationCode.clusterRequiredForContext); + expect( + () async => (await getKubeconfig('invalid_context_cluster.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('userRequiredForContext', () async { + final result = + (await getKubeconfig('invalid_context_user.yaml')).validate(); + expect(result.code, ValidationCode.userRequiredForContext); + expect( + () async => (await getKubeconfig('invalid_context_user.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('namedClusterDuplicate', () async { + final result = + (await getKubeconfig('invalid_clusters_duplicate.yaml')).validate(); + expect(result.code, ValidationCode.namedClusterDuplicate); + expect( + () async => (await getKubeconfig('invalid_clusters_duplicate.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('namedContextDuplicate', () async { + final result = + (await getKubeconfig('invalid_contexts_duplicate.yaml')).validate(); + expect(result.code, ValidationCode.namedContextDuplicate); + expect( + () async => (await getKubeconfig('invalid_contexts_duplicate.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('namedUserDuplicate', () async { + final result = + (await getKubeconfig('invalid_users_duplicate.yaml')).validate(); + expect(result.code, ValidationCode.namedUserDuplicate); + expect( + () async => (await getKubeconfig('invalid_users_duplicate.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('currentContextNotFound', () async { + final result = + (await getKubeconfig('invalid_current_context.yaml')).validate(); + expect(result.code, ValidationCode.currentContextNotFound); + expect( + () async => (await getKubeconfig('invalid_current_context.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clusterNotFoundForContext', () async { + final result = + (await getKubeconfig('invalid_context_cluster_missing.yaml')) + .validate(); + expect(result.code, ValidationCode.clusterNotFoundForContext); + expect( + () async => + (await getKubeconfig('invalid_context_cluster_missing.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('userNotFoundForContext', () async { + final result = + (await getKubeconfig('invalid_context_user_missing.yaml')).validate(); + expect(result.code, ValidationCode.userNotFoundForContext); + expect( + () async => (await getKubeconfig('invalid_context_user_missing.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('namespaceInvalidMaxLengthForContext', () async { + final result = + (await getKubeconfig('invalid_context_namespace_length.yaml')) + .validate(); + expect(result.code, ValidationCode.namespaceInvalidMaxLengthForContext); + expect( + () async => + (await getKubeconfig('invalid_context_namespace_length.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('namespaceFormatNotMatchForContext', () async { + final result = + (await getKubeconfig('invalid_context_namespace_format.yaml')) + .validate(); + expect(result.code, ValidationCode.namespaceFormatNotMatchForContext); + expect( + () async => + (await getKubeconfig('invalid_context_namespace_format.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('certificateAuthorityErrorForCluster', () async { + final result = + (await getKubeconfig('invalid_cluster_certificate_both.yaml')) + .validate(); + expect(result.code, ValidationCode.certificateAuthorityErrorForCluster); + expect( + () async => + (await getKubeconfig('invalid_cluster_certificate_both.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('certificateAuthorityFileErrorForCluster', () async { + final result = + (await getKubeconfig('invalid_cluster_certificate_file.yaml')) + .validate(); + expect( + result.code, + ValidationCode.certificateAuthorityFileErrorForCluster, + ); + expect( + () async => + (await getKubeconfig('invalid_cluster_certificate_file.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('proxyUrlInvalidForCluster', () async { + final result = + (await getKubeconfig('invalid_cluster_proxyurl.yaml')).validate(); + expect(result.code, ValidationCode.proxyUrlInvalidForCluster); + expect( + () async => (await getKubeconfig('invalid_cluster_proxyurl.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('proxyUrlInvalidSchemeForCluster', () async { + final result = + (await getKubeconfig('invalid_cluster_proxyurl_scheme.yaml')) + .validate(); + expect(result.code, ValidationCode.proxyUrlInvalidSchemeForCluster); + expect( + () async => + (await getKubeconfig('invalid_cluster_proxyurl_scheme.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clientCertErrorForUser', () async { + final result = (await getKubeconfig('invalid_user_certificate_both.yaml')) + .validate(); + expect(result.code, ValidationCode.clientCertErrorForUser); + expect( + () async => (await getKubeconfig('invalid_user_certificate_both.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clientKeyErrorForUser', () async { + final result = + (await getKubeconfig('invalid_user_clientkey_both.yaml')).validate(); + expect(result.code, ValidationCode.clientKeyErrorForUser); + expect( + () async => (await getKubeconfig('invalid_user_clientkey_both.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clientKeyNotFoundForUser', () async { + final result = + (await getKubeconfig('invalid_user_clientkey_missing.yaml')) + .validate(); + expect(result.code, ValidationCode.clientKeyNotFoundForUser); + expect( + () async => (await getKubeconfig('invalid_user_clientkey_missing.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clientCertFileErrorForUser', () async { + final result = (await getKubeconfig('invalid_user_certificate_file.yaml')) + .validate(); + expect(result.code, ValidationCode.clientCertFileErrorForUser); + expect( + () async => (await getKubeconfig('invalid_user_certificate_file.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('clientKeyFileErrorForUser', () async { + final result = + (await getKubeconfig('invalid_user_clientkey_file.yaml')).validate(); + expect(result.code, ValidationCode.clientKeyFileErrorForUser); + expect( + () async => (await getKubeconfig('invalid_user_clientkey_file.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('authProviderAndExecErrorForUser', () async { + final result = + (await getKubeconfig('invalid_user_auth_provider.yaml')).validate(); + expect(result.code, ValidationCode.authProviderAndExecErrorForUser); + expect( + () async => (await getKubeconfig('invalid_user_auth_provider.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('execCommandNotFoundForUser', () async { + final result = + (await getKubeconfig('invalid_user_exec_command_missing.yaml')) + .validate(); + expect(result.code, ValidationCode.execCommandNotFoundForUser); + expect( + () async => + (await getKubeconfig('invalid_user_exec_command_missing.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('execApiVersionNotFoundForUser', () async { + final result = + (await getKubeconfig('invalid_user_exec_apiversion_missing.yaml')) + .validate(); + expect(result.code, ValidationCode.execApiVersionNotFoundForUser); + expect( + () async => + (await getKubeconfig('invalid_user_exec_apiversion_missing.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('execEnvNameNotFoundForUser', () async { + final result = + (await getKubeconfig('invalid_user_exec_envname_missing.yaml')) + .validate(); + expect(result.code, ValidationCode.execEnvNameNotFoundForUser); + expect( + () async => + (await getKubeconfig('invalid_user_exec_envname_missing.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('moreThanOneAuthFoundForUser', () async { + final result = + (await getKubeconfig('invalid_user_multi_auth.yaml')).validate(); + expect(result.code, ValidationCode.moreThanOneAuthFoundForUser); + expect( + () async => (await getKubeconfig('invalid_user_multi_auth.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + + test('impersonatingErrorForUser', () async { + final result = + (await getKubeconfig('invalid_user_impersonating.yaml')).validate(); + expect(result.code, ValidationCode.impersonatingErrorForUser); + expect( + () async => (await getKubeconfig('invalid_user_impersonating.yaml')) + .validate(throwExceptions: true), + throwsA(isA()), + ); + }); + }); + + group('KubeconfigException', () { + const kubeconfigException = KubeconfigException( + code: ValidationCode.contextsRequired, + message: '"contexts" was not found', + ); + test('can be instantiated and all props are valid', () { + expect(kubeconfigException, isNotNull); + expect(kubeconfigException.props, isNotNull); + expect(kubeconfigException.toString(), isNotNull); + }); + }); +}