├── .devcontainer └── devcontainer.json ├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md ├── dependabot.yml └── workflows │ ├── buildtest.yaml │ ├── codeql-analysis.yml │ ├── docfx.yaml │ ├── draft.yaml │ └── nuget.yaml ├── .gitignore ├── CONTRIBUTING.md ├── CodeCoverage.runsettings ├── Directory.Build.props ├── Directory.Build.targets ├── Directory.Packages.props ├── LICENSE ├── OWNERS ├── README.md ├── SECURITY_CONTACTS ├── code-of-conduct.md ├── csharp.settings ├── doc ├── .gitignore ├── docfx.json ├── index.md └── toc.yml ├── examples ├── Directory.Build.props ├── Directory.Build.targets ├── aks-kubelogin │ ├── Program.cs │ ├── README.md │ └── aks-kubelogin.csproj ├── aot │ ├── Program.cs │ └── aot.csproj ├── attach │ ├── Attach.cs │ └── attach.csproj ├── clientset │ ├── Program.cs │ └── clientset.csproj ├── cp │ ├── Cp.cs │ └── cp.csproj ├── csrApproval │ ├── Program.cs │ └── csrApproval.csproj ├── customResource │ ├── CustomResourceDefinition.cs │ ├── Program.cs │ ├── README.md │ ├── Utils.cs │ ├── cResource.cs │ ├── config │ │ ├── crd.yaml │ │ └── yaml-cr-instance.yaml │ └── customResource.csproj ├── exec │ ├── Exec.cs │ └── exec.csproj ├── generic │ ├── Generic.cs │ └── generic.csproj ├── labels │ ├── PodList.cs │ └── labels.csproj ├── logs │ ├── Logs.cs │ └── logs.csproj ├── metrics │ ├── Program.cs │ └── metrics.csproj ├── namespace │ ├── NamespaceExample.cs │ └── namespace.csproj ├── openTelemetryConsole │ ├── Program.cs │ └── openTelemetryConsole.csproj ├── patch-aot │ ├── Program.cs │ └── patch-aot.csproj ├── patch │ ├── Program.cs │ └── patch.csproj ├── portforward │ ├── PortForward.cs │ └── portforward.csproj ├── restart │ ├── Program.cs │ └── restart.csproj ├── simple │ ├── PodList.cs │ └── simple.csproj ├── watch │ ├── Program.cs │ └── watch.csproj ├── webApiDependencyInjection │ ├── Controllers │ │ ├── ExampleDependencyInjectionOnConstructorController.cs │ │ └── ExampleDependencyInjectionOnMethodController.cs │ ├── Program.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── webApiDependencyInjection.csproj ├── workerServiceDependencyInjection │ ├── Program.cs │ ├── Worker.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── workerServiceDependencyInjection.csproj └── yaml │ ├── Program.cs │ └── yaml.csproj ├── global.json ├── kubernetes-client.proj ├── kubernetes-client.ruleset ├── logo.png ├── nuget.config ├── src ├── KubernetesClient.Aot │ ├── Global.cs │ ├── KubeConfigModels │ │ ├── AuthProvider.cs │ │ ├── Cluster.cs │ │ ├── ClusterEndpoint.cs │ │ ├── Context.cs │ │ ├── ContextDetails.cs │ │ ├── ExecCredentialResponse.cs │ │ ├── ExternalExecution.cs │ │ ├── K8SConfiguration.cs │ │ ├── StaticContext.cs │ │ ├── User.cs │ │ └── UserCredentials.cs │ ├── KubernetesClient.Aot.csproj │ ├── KubernetesClientConfiguration.ConfigFile.cs │ ├── KubernetesJson.cs │ ├── KubernetesYaml.cs │ ├── SourceGenerationContext.cs │ └── V1PatchJsonConverter.cs ├── KubernetesClient.Classic │ ├── CertUtils.cs │ ├── Global.cs │ ├── Kubernetes.Websocket.Netstandard.cs │ └── KubernetesClient.Classic.csproj ├── KubernetesClient.Kubectl │ ├── Beta │ │ ├── AsyncKubectl.Cordon.cs │ │ ├── AsyncKubectl.Version.cs │ │ ├── AsyncKubectl.cs │ │ ├── Kubectl.Cordon.cs │ │ ├── Kubectl.Version.cs │ │ └── Kubectl.cs │ └── KubernetesClient.Kubectl.csproj ├── KubernetesClient │ ├── AbstractKubernetes.cs │ ├── Authentication │ │ ├── BasicAuthenticationCredentials.cs │ │ ├── ExecTokenProvider.cs │ │ ├── ITokenProvider.cs │ │ ├── OidcTokenProvider.cs │ │ ├── ServiceClientCredentials.cs │ │ ├── StringTokenProvider.cs │ │ ├── TokenCredentials.cs │ │ └── TokenFileAuth.cs │ ├── Autorest │ │ ├── HttpExtensions.cs │ │ ├── HttpMessageWrapper.cs │ │ ├── HttpOperationException.cs │ │ ├── HttpOperationResponse.cs │ │ ├── HttpRequestMessageWrapper.cs │ │ └── HttpResponseMessageWrapper.cs │ ├── ByteBuffer.cs │ ├── CertUtils.cs │ ├── ChannelIndex.cs │ ├── ClientSets │ │ ├── ClientSet.cs │ │ └── ResourceClient.cs │ ├── Exceptions │ │ ├── KubeConfigException.cs │ │ └── KubernetesClientException.cs │ ├── ExecAsyncCallback.cs │ ├── Extensions.cs │ ├── FileSystem.cs │ ├── FloatEmitter.cs │ ├── GeneratedApiVersion.cs │ ├── GenericClient.cs │ ├── Global.cs │ ├── IItems.cs │ ├── IKubernetes.Exec.cs │ ├── IKubernetes.WebSocket.cs │ ├── IKubernetes.cs │ ├── IKubernetesObject.cs │ ├── IMetadata.cs │ ├── ISpec.cs │ ├── IStatus.cs │ ├── IStreamDemuxer.cs │ ├── IValidate.cs │ ├── KubeConfigModels │ │ ├── AuthProvider.cs │ │ ├── Cluster.cs │ │ ├── ClusterEndpoint.cs │ │ ├── Context.cs │ │ ├── ContextDetails.cs │ │ ├── ExecCredentialResponse.cs │ │ ├── ExternalExecution.cs │ │ ├── K8SConfiguration.cs │ │ ├── NamedExtension.cs │ │ ├── User.cs │ │ └── UserCredentials.cs │ ├── Kubernetes.ConfigInit.cs │ ├── Kubernetes.Exec.cs │ ├── Kubernetes.WebSocket.cs │ ├── Kubernetes.cs │ ├── KubernetesClient.csproj │ ├── KubernetesClientConfiguration.ConfigFile.cs │ ├── KubernetesClientConfiguration.InCluster.cs │ ├── KubernetesClientConfiguration.cs │ ├── KubernetesException.cs │ ├── KubernetesJson.cs │ ├── KubernetesMetricsExtensions.cs │ ├── KubernetesObject.cs │ ├── KubernetesRequestDigest.cs │ ├── KubernetesYaml.cs │ ├── LeaderElection │ │ ├── ILock.cs │ │ ├── LeaderElectionConfig.cs │ │ ├── LeaderElectionRecord.cs │ │ ├── LeaderElector.cs │ │ └── ResourceLock │ │ │ ├── ConfigMapLock.cs │ │ │ ├── EndpointsLock.cs │ │ │ ├── LeaseLock.cs │ │ │ ├── MetaObjectAnnotationLock.cs │ │ │ ├── MetaObjectLock.cs │ │ │ └── MultiLock.cs │ ├── LineSeparatedHttpContent.cs │ ├── Models │ │ ├── ContainerMetrics.cs │ │ ├── GeneratedModelVersion.cs │ │ ├── IntOrStringJsonConverter.cs │ │ ├── IntOrStringYamlConverter.cs │ │ ├── IntstrIntOrString.cs │ │ ├── KubernetesEntityAttribute.cs │ │ ├── KubernetesList.cs │ │ ├── ModelExtensions.cs │ │ ├── ModelVersionConverter.cs │ │ ├── NodeMetrics.cs │ │ ├── NodeMetricsList.cs │ │ ├── PodMetrics.cs │ │ ├── PodMetricsList.cs │ │ ├── ResourceQuantity.cs │ │ ├── ResourceQuantityJsonConverter.cs │ │ ├── ResourceQuantityYamlConverter.cs │ │ ├── V1Patch.cs │ │ ├── V1PatchJsonConverter.cs │ │ ├── V1PodTemplateSpec.cs │ │ ├── V1Status.ObjectView.cs │ │ └── V1Status.cs │ ├── MuxedStream.cs │ ├── PrometheusHandler.cs │ ├── StreamDemuxer.cs │ ├── StreamType.cs │ ├── StringQuotingEmitter.cs │ ├── Utilities.cs │ ├── Watcher.cs │ ├── WatcherExt.cs │ ├── WebSocketBuilder.cs │ └── WebSocketProtocol.cs ├── LibKubernetesGenerator │ ├── ApiGenerator.cs │ ├── ClassNameHelper.cs │ ├── ClientSetGenerator.cs │ ├── EmbedResource.cs │ ├── GeneralNameHelper.cs │ ├── GeneratorExecutionContextExt.cs │ ├── IScriptObjectHelper.cs │ ├── KubernetesClientSourceGenerator.cs │ ├── LibKubernetesGenerator.target │ ├── MetaHelper.cs │ ├── ModelExtGenerator.cs │ ├── ModelGenerator.cs │ ├── ParamHelper.cs │ ├── PluralHelper.cs │ ├── ScriptObjectFactory.cs │ ├── SourceGenerationContextGenerator.cs │ ├── StringHelpers.cs │ ├── TypeHelper.cs │ ├── UtilHelper.cs │ ├── VersionConverterStubGenerator.cs │ ├── VersionGenerator.cs │ ├── generators │ │ └── LibKubernetesGenerator │ │ │ └── LibKubernetesGenerator.csproj │ └── templates │ │ ├── AbstractKubernetes.cs.template │ │ ├── Client.cs.template │ │ ├── ClientSet.cs.template │ │ ├── GroupClient.cs.template │ │ ├── IBasicKubernetes.cs.template │ │ ├── IOperations.cs.template │ │ ├── Model.cs.template │ │ ├── ModelExtensions.cs.template │ │ ├── Operations.cs.template │ │ ├── OperationsExtensions.cs.template │ │ └── SourceGenerationContext.cs.template └── nuget.proj ├── stylecop.json ├── swagger.json ├── tests ├── E2E.Aot.Tests │ ├── E2E.Aot.Tests.csproj │ └── MinikubeTests.cs ├── E2E.Tests │ ├── E2E.Tests.csproj │ ├── KubectlTests.cs │ ├── MinikubeFactAttribute.cs │ ├── MinikubeTests.cs │ └── Onebyone.cs ├── Kubectl.Tests │ ├── Kubectl.Tests.csproj │ ├── KubectlTests.Version.cs │ └── KubectlTests.cs ├── KubernetesClient.Classic.Tests │ ├── KubernetesClient.Classic.Tests.csproj │ └── SimpleTests.cs ├── KubernetesClient.Tests │ ├── AssemblyInfo.cs │ ├── AuthTests.cs │ ├── ByteBufferTests.cs │ ├── CertUtilsTests.cs │ ├── CertificateValidationTests.cs │ ├── ExternalExecutionTests.cs │ ├── IntOrStringTests.cs │ ├── ItemsEnumTests.cs │ ├── KubernetesClient.Tests.csproj │ ├── KubernetesClientConfigurationTests.cs │ ├── KubernetesExecTests.cs │ ├── KubernetesJsonTests.cs │ ├── KubernetesMetricsTests.cs │ ├── KubernetesYamlTests.cs │ ├── LeaderElection │ │ └── LeaderElectionTests.cs │ ├── Logging │ │ ├── TestOutputLogger.cs │ │ ├── TestOutputLoggerProvider.cs │ │ └── TestOutputLoggingExtensions.cs │ ├── Mock │ │ ├── MockKubeApiServer.cs │ │ ├── MockWebSocket.cs │ │ ├── MockWebSocketBuilder.cs │ │ └── Server │ │ │ ├── Controllers │ │ │ ├── PodExecController.cs │ │ │ └── PodPortForwardController.cs │ │ │ ├── Startup.cs │ │ │ └── WebSocketTestAdapter.cs │ ├── ModelExtensionTests.cs │ ├── OidcAuthTests.cs │ ├── OperatingSystemDependentFactAttribute.cs │ ├── OperatingSystems.cs │ ├── PodExecTests.cs │ ├── QuantityValueTests.cs │ ├── SerializationTests.cs │ ├── StreamDemuxerTests.cs │ ├── TaskAssert.cs │ ├── TokenFileAuthTests.cs │ ├── UtilityTests.cs │ ├── V1StatusObjectViewTests.cs │ ├── WatchTests.cs │ ├── WebSocketTestBase.cs │ └── assets │ │ ├── apiserver-pfx-data.txt │ │ ├── ca-bundle-correct.crt │ │ ├── ca-bundle-incorrect.crt │ │ ├── ca-bundle-intermediate.crt │ │ ├── ca-bundle-root.crt │ │ ├── ca-bundle.crt │ │ ├── ca-data.txt │ │ ├── ca.crt │ │ ├── ca2.crt │ │ ├── ca3.crt │ │ ├── client-certificate-data.txt │ │ ├── client-key-data.txt │ │ ├── client.crt │ │ ├── client.key │ │ ├── elliptic-client.key │ │ ├── elliptic.crt │ │ ├── gcloud-config-helper.json │ │ ├── kubeconfig.additional-properties.yml │ │ ├── kubeconfig.as-user-extra.yml │ │ ├── kubeconfig.cluster-extensions.yml │ │ ├── kubeconfig.cluster-missmatch.yml │ │ ├── kubeconfig.no-cluster.yml │ │ ├── kubeconfig.no-context-details.yml │ │ ├── kubeconfig.no-context.yml │ │ ├── kubeconfig.no-credentials.yml │ │ ├── kubeconfig.no-current-context.yml │ │ ├── kubeconfig.no-server.yml │ │ ├── kubeconfig.no-user.yml │ │ ├── kubeconfig.preferences-extensions.yml │ │ ├── kubeconfig.relative.yml │ │ ├── kubeconfig.tls-no-skip.yml │ │ ├── kubeconfig.tls-servername.yml │ │ ├── kubeconfig.tls-skip-http.yml │ │ ├── kubeconfig.tls-skip.yml │ │ ├── kubeconfig.user-not-found.yml │ │ ├── kubeconfig.user-oidc.yml │ │ ├── kubeconfig.user-pass.yml │ │ ├── kubeconfig.wildcard-ipv4.yml │ │ ├── kubeconfig.wildcard-ipv6.yml │ │ ├── kubeconfig.wildcard-ipv6_2.yml │ │ ├── kubeconfig.yml │ │ ├── mock-gcloud.cmd │ │ ├── mock-gcloud.sh │ │ ├── token1 │ │ └── token2 └── SkipTestLogger │ ├── SkipTestLogger.cs │ └── SkipTestLogger.csproj └── version.json /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "mcr.microsoft.com/dotnet/sdk:8.0" 3 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | *.cs text=auto diff=csharp 17 | *.vb text=auto 18 | *.resx text=auto 19 | *.c text=auto 20 | *.cpp text=auto 21 | *.cxx text=auto 22 | *.h text=auto 23 | *.hxx text=auto 24 | *.py text=auto 25 | *.rb text=auto 26 | *.java text=auto 27 | *.html text=auto 28 | *.htm text=auto 29 | *.css text=auto 30 | *.scss text=auto 31 | *.sass text=auto 32 | *.less text=auto 33 | *.js text=auto 34 | *.lisp text=auto 35 | *.clj text=auto 36 | *.sql text=auto 37 | *.php text=auto 38 | *.lua text=auto 39 | *.m text=auto 40 | *.asm text=auto 41 | *.erl text=auto 42 | *.fs text=auto 43 | *.fsx text=auto 44 | *.hs text=auto 45 | 46 | *.csproj text=auto 47 | *.vbproj text=auto 48 | *.fsproj text=auto 49 | *.dbproj text=auto 50 | *.sln text=auto eol=crlf 51 | 52 | src/KubernetesClient/generated/** linguist-generated 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Kubernetes C# SDK Client Version** 14 | e.g. `9.0.1` 15 | 16 | **Server Kubernetes Version** 17 | e.g. `1.22.3` 18 | 19 | **Dotnet Runtime Version** 20 | e.g. net6 21 | 22 | **To Reproduce** 23 | Steps to reproduce the behavior: 24 | 25 | **Expected behavior** 26 | A clear and concise description of what you expected to happen. 27 | 28 | **KubeConfig** 29 | If applicable, add a KubeConfig file with secrets redacted. 30 | 31 | **Where do you run your app with Kubernetes SDK (please complete the following information):** 32 | - OS: [e.g. Linux] 33 | - Environment [e.g. container] 34 | - Cloud [e.g. Azure] 35 | 36 | **Additional context** 37 | Add any other context about the problem here. 38 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | 9 | # Maintain dependencies for GitHub Actions 10 | - package-ecosystem: "github-actions" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | # Allow up to 5 open pull requests for GitHub Actions dependencies 15 | open-pull-requests-limit: 5 16 | labels: 17 | - "dependencies" 18 | # Rebase open pull requests when changes are detected 19 | rebase-strategy: "auto" 20 | 21 | # Maintain dependencies for NuGet packages 22 | - package-ecosystem: "nuget" 23 | directory: "/" 24 | schedule: 25 | interval: "daily" 26 | # Allow up to 10 open pull requests for NuGet dependencies 27 | open-pull-requests-limit: 10 28 | labels: 29 | - "dependencies" 30 | # Rebase open pull requests when changes are detected 31 | rebase-strategy: "auto" 32 | -------------------------------------------------------------------------------- /.github/workflows/docfx.yaml: -------------------------------------------------------------------------------- 1 | name: Docfx 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | # Allows you to run this workflow manually from the Actions tab 8 | workflow_dispatch: 9 | 10 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 11 | permissions: 12 | contents: read 13 | pages: write 14 | id-token: write 15 | 16 | # Allow one concurrent deployment 17 | concurrency: 18 | group: "pages" 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | docfx: 23 | runs-on: ubuntu-latest 24 | environment: 25 | name: github-pages 26 | url: ${{ steps.deployment.outputs.page_url }} 27 | steps: 28 | - uses: actions/checkout@v4 29 | with: 30 | fetch-depth: 0 31 | 32 | - name: Setup dotnet 33 | uses: actions/setup-dotnet@v4 34 | with: 35 | dotnet-version: | 36 | 8.0.x 37 | 9.0.x 38 | 39 | - name: Build 40 | run: dotnet build -c Release 41 | 42 | - uses: nunit/docfx-action@v4.1.0 43 | name: Build Documentation 44 | with: 45 | args: doc/docfx.json 46 | 47 | - name: Setup Pages 48 | uses: actions/configure-pages@v5 49 | - name: Upload artifact 50 | uses: actions/upload-pages-artifact@v3 51 | with: 52 | # Upload entire repository 53 | path: doc/_site 54 | - name: Deploy to GitHub Pages 55 | id: deployment 56 | uses: actions/deploy-pages@v4 57 | -------------------------------------------------------------------------------- /.github/workflows/draft.yaml: -------------------------------------------------------------------------------- 1 | name: Draft Release 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | 10 | jobs: 11 | draft: 12 | 13 | runs-on: windows-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Setup dotnet 21 | uses: actions/setup-dotnet@v4 22 | with: 23 | dotnet-version: | 24 | 8.0.x 25 | 9.0.x 26 | 27 | - name: dotnet restore 28 | run: dotnet restore --verbosity minimal --configfile nuget.config 29 | 30 | - name: dotnet test 31 | run: dotnet test 32 | 33 | - uses: dotnet/nbgv@master 34 | with: 35 | setAllVars: true 36 | 37 | - name: create release 38 | shell: pwsh 39 | env: 40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | run: | 42 | gh release create -d --generate-notes v$env:NBGV_NuGetPackageVersion 43 | -------------------------------------------------------------------------------- /.github/workflows/nuget.yaml: -------------------------------------------------------------------------------- 1 | name: Nuget 2 | 3 | on: 4 | release: 5 | types: [ released ] 6 | 7 | jobs: 8 | nuget: 9 | 10 | runs-on: windows-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: Setup dotnet 18 | uses: actions/setup-dotnet@v4 19 | with: 20 | dotnet-version: | 21 | 8.0.x 22 | 9.0.x 23 | 24 | - name: dotnet restore 25 | run: dotnet restore --verbosity minimal --configfile nuget.config 26 | 27 | - name: dotnet test 28 | run: dotnet test 29 | 30 | - name: dotnet pack 31 | run: dotnet pack -c Release src/nuget.proj -o pkg --include-symbols 32 | 33 | - name: dotnet nuget push 34 | run: | 35 | dotnet nuget push pkg\*.nupkg -s https://nuget.pkg.github.com/$env:GITHUB_REPOSITORY_OWNER -k ${{ secrets.GITHUB_TOKEN }} --skip-duplicate 36 | dotnet nuget push pkg\*.nupkg -s https://www.nuget.org/ -k ${{ secrets.nuget_api_key }} --skip-duplicate 37 | 38 | 39 | ## Remove old versions of NuGet packages form github NuGet feed 40 | nuget-delete-old-packages: 41 | name: "Delete Old NuGet" 42 | needs: [nuget] 43 | strategy: 44 | matrix: 45 | nuget-package: 46 | - "KubernetesClient" 47 | - "KubernetesClient.Classic" 48 | runs-on: ubuntu-latest 49 | permissions: 50 | packages: write 51 | 52 | steps: 53 | - name: Delete old NuGet packages 54 | uses: actions/delete-package-versions@v5 55 | with: 56 | owner: ${{ env.GITHUB_REPOSITORY_OWNER }} 57 | token: ${{ secrets.GITHUB_TOKEN }} 58 | package-name: ${{ matrix.nuget-package }} 59 | package-type: nuget 60 | min-versions-to-keep: 10 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .vs 3 | obj/ 4 | bin/ 5 | **/TestResults 6 | 7 | # User-specific VS files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # JetBrains Rider 14 | .idea/ 15 | *.sln.iml 16 | 17 | launchSettings.json 18 | *.DotSettings 19 | 20 | *.sln -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for taking the time to join our community and start contributing! 4 | 5 | Please remember to read and observe the [Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). 6 | 7 | This project accepts contribution via github [pull requests](https://help.github.com/articles/about-pull-requests/). This document outlines the process to help get your contribution accepted. Please also read the [Kubernetes contributor guide](https://github.com/kubernetes/community/blob/master/contributors/guide/README.md) which provides detailed instructions on how to get your ideas and bug fixes seen and accepted. 8 | 9 | ## Sign the Contributor License Agreement 10 | We'd love to accept your patches! Before we can accept them you need to sign Cloud Native Computing Foundation (CNCF) [CLA](https://github.com/kubernetes/community/blob/master/CLA.md). 11 | 12 | ## Reporting an issue 13 | If you have any problem with the package or any suggestions, please file an [issue](https://github.com/kubernetes-client/csharp/issues). 14 | 15 | ## Contributing a Patch 16 | 1. Submit an issue describing your proposed change to the repo. 17 | 2. Fork this repo, develop and test your code changes. 18 | 3. Submit a pull request. 19 | 4. The bot will automatically assigns someone to review your PR. Check the full list of bot commands [here](https://prow.k8s.io/command-help). 20 | 21 | ### Contact 22 | You can reach the maintainers of this project at [SIG API Machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery) or on the [#kubernetes-client](https://kubernetes.slack.com/messages/kubernetes-client) channel on the Kubernetes slack. 23 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - brendandburns 5 | - tg123 6 | reviewers: 7 | - brendandburns 8 | - tg123 9 | emeritus_approvers: 10 | - krabhishek8260 # 4/4/2022 11 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Team to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | brendandburns 14 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /csharp.settings: -------------------------------------------------------------------------------- 1 | export KUBERNETES_BRANCH=v1.33.0 2 | export CLIENT_VERSION=0.0.1 3 | export PACKAGE_NAME=k8s 4 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | 11 | api -------------------------------------------------------------------------------- /doc/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "KubernetesClient/KubernetesClient.csproj" 8 | ], 9 | "src": "../src" 10 | } 11 | ], 12 | "dest": "api", 13 | "disableGitFeatures": false, 14 | "disableDefaultFilter": false 15 | } 16 | ], 17 | "build": { 18 | "content": [ 19 | { 20 | "files": [ 21 | "api/**.yml", 22 | "index.md", 23 | "toc.yml" 24 | ] 25 | } 26 | ], 27 | "dest": "_site", 28 | "globalMetadataFiles": [], 29 | "fileMetadataFiles": [], 30 | "template": [ 31 | "default" 32 | ], 33 | "postProcessors": [], 34 | "markdownEngineName": "markdig", 35 | "noLangKeyword": false, 36 | "keepFileLink": false, 37 | "cleanupCacheHistory": false, 38 | "disableGitFeatures": false 39 | } 40 | } -------------------------------------------------------------------------------- /doc/index.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /doc/toc.yml: -------------------------------------------------------------------------------- 1 | - name: API Documentation 2 | href: api/k8s.yml 3 | -------------------------------------------------------------------------------- /examples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net9.0 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/aks-kubelogin/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using System; 3 | using System.IO; 4 | using System.Text; 5 | 6 | var server = "https://example.hcp.eastus.azmk8s.io"; // the server url of your aks 7 | var clientid = "00000000-0000-0000-0000-000000000000"; // the client id of the your msi 8 | var kubelogin = @"C:\bin\kubelogin.exe"; // the path to the kubelogin.exe 9 | 10 | using var configstream = new MemoryStream(Encoding.ASCII.GetBytes($""" 11 | apiVersion: v1 12 | clusters: 13 | - cluster: 14 | insecure-skip-tls-verify: true 15 | server: {server} 16 | name: aks 17 | contexts: 18 | - context: 19 | cluster: aks 20 | user: msi 21 | name: aks 22 | current-context: aks 23 | kind: Config 24 | users: 25 | - name: msi 26 | user: 27 | exec: 28 | apiVersion: client.authentication.k8s.io/v1beta1 29 | args: 30 | - get-token 31 | - --login 32 | - msi 33 | - --server-id 34 | - 6dae42f8-4368-4678-94ff-3960e28e3630 35 | - --client-id 36 | - {clientid} 37 | command: {kubelogin} 38 | env: null 39 | """)); 40 | 41 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(configstream); 42 | IKubernetes client = new Kubernetes(config); 43 | Console.WriteLine("Starting Request!"); 44 | 45 | var list = client.CoreV1.ListNamespacedPod("default"); 46 | foreach (var item in list.Items) 47 | { 48 | Console.WriteLine(item.Metadata.Name); 49 | } 50 | -------------------------------------------------------------------------------- /examples/aks-kubelogin/README.md: -------------------------------------------------------------------------------- 1 | # AKS C# example using kubelogin + MSI 2 | 3 | This example shows how to use the [kubelogin](https://github.com/Azure/kubelogin) to authenticate using [managed identities](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) with Azure Kubernetes Service (AKS) using the C# SDK. 4 | 5 | 6 | ## Prerequisites 7 | 8 | - turn on AAD support for AKS, see [here](https://docs.microsoft.com/en-us/azure/aks/managed-aad) 9 | - create a managed identity for the AKS cluster 10 | - assign the managed identity the `Azure Kubernetes Service RBAC Cluster Admin` (or other RBAC permission) on the AKS cluster 11 | - assign the managed identity to the VM, see [here](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/qs-configure-portal-windows-vm) 12 | - install the [kubelogin](https://github.com/Azure/kubelogin) to your machine 13 | 14 | ## Running the code 15 | 16 | *You must the the code on VM with MSI* 17 | 18 | - Replace `server` with the address of your AKS cluster 19 | - Replace `clientid` with the client id of the managed identity 20 | - Replace `kubelogin` with the path to the kubelogin executable 21 | 22 | ``` 23 | dotnet run 24 | ``` -------------------------------------------------------------------------------- /examples/aks-kubelogin/aks-kubelogin.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | 5 | -------------------------------------------------------------------------------- /examples/aot/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | 3 | var config = KubernetesClientConfiguration.BuildDefaultConfig(); 4 | IKubernetes client = new Kubernetes(config); 5 | Console.WriteLine("Starting Request!"); 6 | 7 | var list = client.CoreV1.ListNamespacedPod("default"); 8 | foreach (var item in list.Items) 9 | { 10 | Console.WriteLine(item.Metadata.Name); 11 | } 12 | 13 | if (list.Items.Count == 0) 14 | { 15 | Console.WriteLine("Empty!"); 16 | } -------------------------------------------------------------------------------- /examples/aot/aot.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | enable 5 | enable 6 | true 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/attach/Attach.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 7 | IKubernetes client = new Kubernetes(config); 8 | Console.WriteLine("Starting Request!"); 9 | 10 | var list = client.CoreV1.ListNamespacedPod("default"); 11 | var pod = list.Items[0]; 12 | await AttachToPod(client, pod).ConfigureAwait(false); 13 | 14 | async Task AttachToPod(IKubernetes client, V1Pod pod) 15 | { 16 | var webSocket = 17 | await client.WebSocketNamespacedPodAttachAsync(pod.Metadata.Name, "default", 18 | pod.Spec.Containers[0].Name).ConfigureAwait(false); 19 | 20 | var demux = new StreamDemuxer(webSocket); 21 | demux.Start(); 22 | 23 | var buff = new byte[4096]; 24 | var stream = demux.GetStream(1, 1); 25 | while (true) 26 | { 27 | var read = stream.Read(buff, 0, 4096); 28 | var str = System.Text.Encoding.Default.GetString(buff); 29 | Console.WriteLine(str); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/attach/attach.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/clientset/Program.cs: -------------------------------------------------------------------------------- 1 | // See https://aka.ms/new-console-template for more information 2 | using k8s; 3 | using k8s.ClientSets; 4 | using System.Threading.Tasks; 5 | 6 | namespace clientset 7 | { 8 | internal class Program 9 | { 10 | private static async Task Main(string[] args) 11 | { 12 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 13 | var client = new Kubernetes(config); 14 | 15 | ClientSet clientSet = new ClientSet(client); 16 | var list = await clientSet.CoreV1.Pod.ListAsync("default").ConfigureAwait(false); 17 | foreach (var item in list) 18 | { 19 | System.Console.WriteLine(item.Metadata.Name); 20 | } 21 | 22 | var pod = await clientSet.CoreV1.Pod.GetAsync("test","default").ConfigureAwait(false); 23 | System.Console.WriteLine(pod?.Metadata?.Name); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/clientset/clientset.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Exe 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/cp/cp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/csrApproval/csrApproval.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/customResource/CustomResourceDefinition.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | using System.Collections.Generic; 4 | using System.Text.Json.Serialization; 5 | 6 | [module: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "CA1724:TypeNamesShouldNotMatchNamespaces", Justification = "This is just an example.")] 7 | [module: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleClass", Justification = "This is just an example.")] 8 | 9 | namespace customResource 10 | { 11 | public class CustomResourceDefinition 12 | { 13 | public string Version { get; set; } 14 | 15 | public string Group { get; set; } 16 | 17 | public string PluralName { get; set; } 18 | 19 | public string Kind { get; set; } 20 | 21 | public string Namespace { get; set; } 22 | } 23 | 24 | public abstract class CustomResource : KubernetesObject, IMetadata 25 | { 26 | [JsonPropertyName("metadata")] 27 | public V1ObjectMeta Metadata { get; set; } 28 | } 29 | 30 | public abstract class CustomResource : CustomResource 31 | { 32 | [JsonPropertyName("spec")] 33 | public TSpec Spec { get; set; } 34 | 35 | [JsonPropertyName("status")] 36 | public TStatus Status { get; set; } 37 | } 38 | 39 | public class CustomResourceList : KubernetesObject 40 | where T : CustomResource 41 | { 42 | public V1ListMeta Metadata { get; set; } 43 | public List Items { get; set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/customResource/README.md: -------------------------------------------------------------------------------- 1 | # Custom Resource Client Example 2 | 3 | This example demonstrates how to use the C# Kubernetes Client library to create, get and list custom resources. 4 | 5 | ## Pre-requisits 6 | 7 | Make sure your have added the library package 8 | 9 | ```shell 10 | dotnet add package KubernetesClient 11 | ``` 12 | 13 | ## Create Custom Resource Definition (CRD) 14 | 15 | Make sure the [CRD](./config/crd.yaml) is created, in order to create an instance of it after. 16 | 17 | ```shell 18 | kubectl create -f ./config/crd.yaml 19 | ``` 20 | 21 | You can test that the CRD is successfully added, by creating an [instance](./config/yaml-cr-instance.yaml) of it using kubectl: 22 | 23 | ```shell 24 | kubectl create -f ./config/yaml-cr-instance.yaml 25 | ``` 26 | 27 | ```shell 28 | kubectl get customresources.csharp.com 29 | ``` 30 | 31 | ## Execute the code 32 | 33 | The client uses the `BuildConfigFromConfigFile()` function. If the KUBECONFIG environment variable is set, then that path to the k8s config file will be used. 34 | 35 | `dotnet run` 36 | 37 | Expected output: 38 | 39 | ``` 40 | strating main()... 41 | working with CRD: customresources.csharp.com 42 | creating CR cr-instance-london 43 | CR list: 44 | - CR Item 0 = cr-instance-london 45 | - CR Item 1 = cr-instance-paris 46 | fetchedCR = cr-instance-london (Labels: {identifier : city, newKey : newValue}), Spec: London 47 | Deleted the CR 48 | ``` 49 | 50 | ## Under the hood 51 | 52 | For more details, you can look at the Generic client [implementation](https://github.com/kubernetes-client/csharp/blob/master/src/KubernetesClient/GenericClient.cs) 53 | 54 | -------------------------------------------------------------------------------- /examples/customResource/Utils.cs: -------------------------------------------------------------------------------- 1 | using k8s.Models; 2 | using System.Collections.Generic; 3 | namespace customResource 4 | { 5 | public class Utils 6 | { 7 | // creats a CRD definition 8 | public static CustomResourceDefinition MakeCRD() 9 | { 10 | var myCRD = new CustomResourceDefinition() 11 | { 12 | Kind = "CResource", 13 | Group = "csharp.com", 14 | Version = "v1alpha1", 15 | PluralName = "customresources", 16 | }; 17 | 18 | return myCRD; 19 | } 20 | 21 | // creats a CR instance 22 | public static CResource MakeCResource() 23 | { 24 | var myCResource = new CResource() 25 | { 26 | Kind = "CResource", 27 | ApiVersion = "csharp.com/v1alpha1", 28 | Metadata = new V1ObjectMeta 29 | { 30 | Name = "cr-instance-london", 31 | NamespaceProperty = "default", 32 | Labels = new Dictionary 33 | { 34 | { 35 | "identifier", "city" 36 | }, 37 | }, 38 | }, 39 | // spec 40 | Spec = new CResourceSpec 41 | { 42 | CityName = "London", 43 | }, 44 | }; 45 | return myCResource; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/customResource/cResource.cs: -------------------------------------------------------------------------------- 1 | using k8s.Models; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace customResource 5 | { 6 | public class CResource : CustomResource 7 | { 8 | public override string ToString() 9 | { 10 | var labels = "{"; 11 | foreach (var kvp in Metadata.Labels) 12 | { 13 | labels += kvp.Key + " : " + kvp.Value + ", "; 14 | } 15 | 16 | labels = labels.TrimEnd(',', ' ') + "}"; 17 | 18 | return $"{Metadata.Name} (Labels: {labels}), Spec: {Spec.CityName}"; 19 | } 20 | } 21 | 22 | public class CResourceSpec 23 | { 24 | [JsonPropertyName("cityName")] 25 | public string CityName { get; set; } 26 | } 27 | 28 | public class CResourceStatus : V1Status 29 | { 30 | [JsonPropertyName("temperature")] 31 | public string Temperature { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/customResource/config/crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: customresources.csharp.com 5 | spec: 6 | group: csharp.com 7 | versions: 8 | - name: v1alpha1 9 | storage: true 10 | served: true 11 | schema: 12 | openAPIV3Schema: 13 | type: object 14 | properties: 15 | spec: 16 | type: object 17 | properties: 18 | cityName: 19 | type: string 20 | names: 21 | kind: CResource 22 | plural: customresources 23 | scope: Namespaced 24 | -------------------------------------------------------------------------------- /examples/customResource/config/yaml-cr-instance.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: csharp.com/v1alpha1 2 | kind: CResource 3 | metadata: 4 | name: cr-instance-paris 5 | namespace: default 6 | spec: 7 | cityName: Paris 8 | -------------------------------------------------------------------------------- /examples/customResource/customResource.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/exec/Exec.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 7 | IKubernetes client = new Kubernetes(config); 8 | Console.WriteLine("Starting Request!"); 9 | 10 | var list = client.CoreV1.ListNamespacedPod("default"); 11 | var pod = list.Items[0]; 12 | await ExecInPod(client, pod).ConfigureAwait(false); 13 | 14 | async Task ExecInPod(IKubernetes client, V1Pod pod) 15 | { 16 | var webSocket = 17 | await client.WebSocketNamespacedPodExecAsync(pod.Metadata.Name, "default", "ls", 18 | pod.Spec.Containers[0].Name).ConfigureAwait(false); 19 | 20 | var demux = new StreamDemuxer(webSocket); 21 | demux.Start(); 22 | 23 | var buff = new byte[4096]; 24 | var stream = demux.GetStream(1, 1); 25 | var read = stream.Read(buff, 0, 4096); 26 | var str = System.Text.Encoding.Default.GetString(buff); 27 | Console.WriteLine(str); 28 | } 29 | -------------------------------------------------------------------------------- /examples/exec/exec.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/generic/Generic.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | using System; 4 | 5 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 6 | IKubernetes client = new Kubernetes(config); 7 | var generic = new GenericClient(client, "", "v1", "nodes"); 8 | var node = await generic.ReadAsync("kube0").ConfigureAwait(false); 9 | Console.WriteLine(node.Metadata.Name); 10 | 11 | var genericPods = new GenericClient(client, "", "v1", "pods"); 12 | var pods = await genericPods.ListNamespacedAsync("default").ConfigureAwait(false); 13 | foreach (var pod in pods.Items) 14 | { 15 | Console.WriteLine(pod.Metadata.Name); 16 | } 17 | -------------------------------------------------------------------------------- /examples/generic/generic.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/labels/PodList.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 6 | IKubernetes client = new Kubernetes(config); 7 | Console.WriteLine("Starting Request!"); 8 | 9 | var list = client.CoreV1.ListNamespacedService("default"); 10 | foreach (var item in list.Items) 11 | { 12 | Console.WriteLine("Pods for service: " + item.Metadata.Name); 13 | Console.WriteLine("=-=-=-=-=-=-=-=-=-=-="); 14 | if (item.Spec == null || item.Spec.Selector == null) 15 | { 16 | continue; 17 | } 18 | 19 | var labels = new List(); 20 | foreach (var key in item.Spec.Selector) 21 | { 22 | labels.Add(key.Key + "=" + key.Value); 23 | } 24 | 25 | var labelStr = string.Join(",", labels.ToArray()); 26 | Console.WriteLine(labelStr); 27 | var podList = client.CoreV1.ListNamespacedPod("default", labelSelector: labelStr); 28 | foreach (var pod in podList.Items) 29 | { 30 | Console.WriteLine(pod.Metadata.Name); 31 | } 32 | 33 | if (podList.Items.Count == 0) 34 | { 35 | Console.WriteLine("Empty!"); 36 | } 37 | 38 | Console.WriteLine(); 39 | } 40 | -------------------------------------------------------------------------------- /examples/labels/labels.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/logs/Logs.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using System; 3 | 4 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 5 | IKubernetes client = new Kubernetes(config); 6 | Console.WriteLine("Starting Request!"); 7 | 8 | var list = client.CoreV1.ListNamespacedPod("default"); 9 | if (list.Items.Count == 0) 10 | { 11 | Console.WriteLine("No pods!"); 12 | return; 13 | } 14 | 15 | var pod = list.Items[0]; 16 | 17 | var response = await client.CoreV1.ReadNamespacedPodLogWithHttpMessagesAsync( 18 | pod.Metadata.Name, 19 | pod.Metadata.NamespaceProperty, container: pod.Spec.Containers[0].Name, follow: true).ConfigureAwait(false); 20 | var stream = response.Body; 21 | stream.CopyTo(Console.OpenStandardOutput()); 22 | -------------------------------------------------------------------------------- /examples/logs/logs.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/metrics/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using System; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | async Task NodesMetrics(IKubernetes client) 7 | { 8 | var nodesMetrics = await client.GetKubernetesNodesMetricsAsync().ConfigureAwait(false); 9 | 10 | foreach (var item in nodesMetrics.Items) 11 | { 12 | Console.WriteLine(item.Metadata.Name); 13 | 14 | foreach (var metric in item.Usage) 15 | { 16 | Console.WriteLine($"{metric.Key}: {metric.Value}"); 17 | } 18 | } 19 | } 20 | 21 | async Task PodsMetrics(IKubernetes client) 22 | { 23 | var podsMetrics = await client.GetKubernetesPodsMetricsAsync().ConfigureAwait(false); 24 | 25 | if (!podsMetrics.Items.Any()) 26 | { 27 | Console.WriteLine("Empty"); 28 | } 29 | 30 | foreach (var item in podsMetrics.Items) 31 | { 32 | foreach (var container in item.Containers) 33 | { 34 | Console.WriteLine(container.Name); 35 | 36 | foreach (var metric in container.Usage) 37 | { 38 | Console.WriteLine($"{metric.Key}: {metric.Value}"); 39 | } 40 | } 41 | 42 | Console.Write(Environment.NewLine); 43 | } 44 | } 45 | 46 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 47 | var client = new Kubernetes(config); 48 | 49 | await NodesMetrics(client).ConfigureAwait(false); 50 | Console.WriteLine(Environment.NewLine); 51 | await PodsMetrics(client).ConfigureAwait(false); 52 | -------------------------------------------------------------------------------- /examples/metrics/metrics.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/namespace/namespace.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/openTelemetryConsole/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using OpenTelemetry; 3 | using OpenTelemetry.Resources; 4 | using OpenTelemetry.Trace; 5 | 6 | var serviceName = "MyCompany.MyProduct.MyService"; 7 | var serviceVersion = "1.0.0"; 8 | 9 | // Create the OpenTelemetry TraceProvide with HttpClient instrumentation enabled 10 | // NOTE: for this example telemetry will be exported to console 11 | using var tracerProvider = Sdk.CreateTracerProviderBuilder() 12 | .AddSource(serviceName) 13 | .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName: serviceName, serviceVersion: serviceVersion)) 14 | .AddHttpClientInstrumentation() 15 | .AddConsoleExporter() 16 | .Build(); 17 | 18 | // Load kubernetes configuration 19 | var config = KubernetesClientConfiguration.BuildDefaultConfig(); 20 | 21 | // Create an istance of Kubernetes client 22 | IKubernetes client = new Kubernetes(config); 23 | 24 | // Read the list of pods contained in default namespace 25 | var list = client.CoreV1.ListNamespacedPod("default"); 26 | 27 | // Print the name of pods 28 | foreach (var item in list.Items) 29 | { 30 | Console.WriteLine(item.Metadata.Name); 31 | } 32 | 33 | // Or empty if there are no pods 34 | if (list.Items.Count == 0) 35 | { 36 | Console.WriteLine("Empty!"); 37 | } 38 | -------------------------------------------------------------------------------- /examples/openTelemetryConsole/openTelemetryConsole.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/patch-aot/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | 4 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 5 | IKubernetes client = new Kubernetes(config); 6 | Console.WriteLine("Starting Request!"); 7 | 8 | var pod = client.CoreV1.ListNamespacedPod("default").Items.First(); 9 | var name = pod.Metadata.Name; 10 | PrintLabels(pod); 11 | 12 | var patchStr = @" 13 | { 14 | ""metadata"": { 15 | ""labels"": { 16 | ""test"": ""test"" 17 | } 18 | } 19 | }"; 20 | 21 | client.CoreV1.PatchNamespacedPod(new V1Patch(patchStr, V1Patch.PatchType.MergePatch), name, "default"); 22 | PrintLabels(client.CoreV1.ReadNamespacedPod(name, "default")); 23 | 24 | static void PrintLabels(V1Pod pod) 25 | { 26 | Console.WriteLine($"Labels: for {pod.Metadata.Name}"); 27 | foreach (var (k, v) in pod.Metadata.Labels) 28 | { 29 | Console.WriteLine($"{k} : {v}"); 30 | } 31 | 32 | Console.WriteLine("=-=-=-=-=-=-=-=-=-=-="); 33 | } 34 | -------------------------------------------------------------------------------- /examples/patch-aot/patch-aot.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | enable 5 | enable 6 | true 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/patch/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | using System; 4 | using System.Linq; 5 | 6 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 7 | IKubernetes client = new Kubernetes(config); 8 | Console.WriteLine("Starting Request!"); 9 | 10 | var pod = client.CoreV1.ListNamespacedPod("default").Items.First(); 11 | var name = pod.Metadata.Name; 12 | PrintLabels(pod); 13 | 14 | var patchStr = @" 15 | { 16 | ""metadata"": { 17 | ""labels"": { 18 | ""test"": ""test"" 19 | } 20 | } 21 | }"; 22 | 23 | client.CoreV1.PatchNamespacedPod(new V1Patch(patchStr, V1Patch.PatchType.MergePatch), name, "default"); 24 | PrintLabels(client.CoreV1.ReadNamespacedPod(name, "default")); 25 | 26 | void PrintLabels(V1Pod pod) 27 | { 28 | Console.WriteLine($"Labels: for {pod.Metadata.Name}"); 29 | foreach (var (k, v) in pod.Metadata.Labels) 30 | { 31 | Console.WriteLine($"{k} : {v}"); 32 | } 33 | 34 | Console.WriteLine("=-=-=-=-=-=-=-=-=-=-="); 35 | } 36 | -------------------------------------------------------------------------------- /examples/patch/patch.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/portforward/portforward.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/restart/restart.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/simple/PodList.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using System; 3 | 4 | var config = KubernetesClientConfiguration.BuildDefaultConfig(); 5 | IKubernetes client = new Kubernetes(config); 6 | Console.WriteLine("Starting Request!"); 7 | 8 | var list = client.CoreV1.ListNamespacedPod("default"); 9 | foreach (var item in list.Items) 10 | { 11 | Console.WriteLine(item.Metadata.Name); 12 | } 13 | 14 | if (list.Items.Count == 0) 15 | { 16 | Console.WriteLine("Empty!"); 17 | } 18 | -------------------------------------------------------------------------------- /examples/simple/simple.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/watch/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(); 8 | 9 | IKubernetes client = new Kubernetes(config); 10 | 11 | var podlistResp = client.CoreV1.ListNamespacedPodWithHttpMessagesAsync("default", watch: true); 12 | // C# 8 required https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8 13 | await foreach (var (type, item) in podlistResp.WatchAsync().ConfigureAwait(false)) 14 | { 15 | Console.WriteLine("==on watch event=="); 16 | Console.WriteLine(type); 17 | Console.WriteLine(item.Metadata.Name); 18 | Console.WriteLine("==on watch event=="); 19 | } 20 | 21 | #pragma warning disable CS8321 // Remove unused private members 22 | void WatchUsingCallback(IKubernetes client) 23 | #pragma warning restore CS8321 // Remove unused private members 24 | { 25 | var podlistResp = client.CoreV1.ListNamespacedPodWithHttpMessagesAsync("default", watch: true); 26 | using (podlistResp.Watch((type, item) => 27 | { 28 | Console.WriteLine("==on watch event=="); 29 | Console.WriteLine(type); 30 | Console.WriteLine(item.Metadata.Name); 31 | Console.WriteLine("==on watch event=="); 32 | })) 33 | { 34 | Console.WriteLine("press ctrl + c to stop watching"); 35 | 36 | var ctrlc = new ManualResetEventSlim(false); 37 | Console.CancelKeyPress += (sender, eventArgs) => ctrlc.Set(); 38 | ctrlc.Wait(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/watch/watch.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/webApiDependencyInjection/Controllers/ExampleDependencyInjectionOnConstructorController.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace webApiDependencyInjection.Controllers 5 | { 6 | [ApiController] 7 | [Route("[controller]")] 8 | public class ExampleDependencyInjectionOnConstructorController : ControllerBase 9 | { 10 | private readonly IKubernetes kubernetesClient; 11 | 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// Injects the Kubernetes client into the controller. 15 | /// 16 | /// The Kubernetes client to interact with the Kubernetes API. 17 | public ExampleDependencyInjectionOnConstructorController(IKubernetes kubernetesClient) 18 | { 19 | this.kubernetesClient = kubernetesClient; 20 | } 21 | 22 | /// 23 | /// Retrieves the names of all pods in the default namespace using the injected Kubernetes client. 24 | /// 25 | /// A collection of pod names in the default namespace. 26 | [HttpGet] 27 | public IEnumerable GetPods() 28 | { 29 | // Read the list of pods contained in the default namespace 30 | var podList = this.kubernetesClient.CoreV1.ListNamespacedPod("default"); 31 | 32 | // Return names of pods 33 | return podList.Items.Select(pod => pod.Metadata.Name); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/webApiDependencyInjection/Controllers/ExampleDependencyInjectionOnMethodController.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace webApiDependencyInjection.Controllers 5 | { 6 | [ApiController] 7 | [Route("[controller]")] 8 | public class ExampleDependencyInjectionOnMethodController : ControllerBase 9 | { 10 | /// 11 | /// Example using the kubernetes client injected directly into the method ([FromServices] IKubernetes kubernetesClient). 12 | /// 13 | /// The Kubernetes client instance injected via dependency injection. 14 | /// A collection of pod names in the default namespace. 15 | [HttpGet] 16 | public IEnumerable GetPods([FromServices] IKubernetes kubernetesClient) 17 | { 18 | ArgumentNullException.ThrowIfNull(kubernetesClient); 19 | 20 | // Read the list of pods contained in default namespace 21 | var podList = kubernetesClient.CoreV1.ListNamespacedPod("default"); 22 | 23 | // Return names of pods 24 | return podList.Items.Select(pod => pod.Metadata.Name); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/webApiDependencyInjection/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | 5 | // Load kubernetes configuration 6 | var kubernetesClientConfig = KubernetesClientConfiguration.BuildDefaultConfig(); 7 | 8 | // Register Kubernetes client interface as sigleton 9 | builder.Services.AddSingleton(_ => new Kubernetes(kubernetesClientConfig)); 10 | 11 | // Add services to the container. 12 | builder.Services.AddEndpointsApiExplorer(); 13 | builder.Services.AddSwaggerGen(); 14 | 15 | builder.Services.AddControllers(); 16 | 17 | var app = builder.Build(); 18 | 19 | // Configure the HTTP request pipeline. 20 | if (app.Environment.IsDevelopment()) 21 | { 22 | app.UseSwagger(); 23 | app.UseSwaggerUI(); 24 | } 25 | 26 | app.UseAuthorization(); 27 | 28 | app.MapControllers(); 29 | 30 | // Start the service 31 | app.Run(); 32 | 33 | 34 | // Swagger ui can be accesse at: http://localhost:/swagger 35 | -------------------------------------------------------------------------------- /examples/webApiDependencyInjection/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/webApiDependencyInjection/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /examples/webApiDependencyInjection/webApiDependencyInjection.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/workerServiceDependencyInjection/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using workerServiceDependencyInjection; 3 | 4 | IHost host = Host.CreateDefaultBuilder(args) 5 | .ConfigureServices(services => 6 | { 7 | // Load kubernetes configuration 8 | var kubernetesClientConfig = KubernetesClientConfiguration.BuildDefaultConfig(); 9 | 10 | // Register Kubernetes client interface as sigleton 11 | services.AddSingleton(_ => new Kubernetes(kubernetesClientConfig)); 12 | 13 | services.AddHostedService(); 14 | }) 15 | .Build(); 16 | 17 | await host.RunAsync().ConfigureAwait(false); 18 | -------------------------------------------------------------------------------- /examples/workerServiceDependencyInjection/Worker.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | 3 | namespace workerServiceDependencyInjection 4 | { 5 | public class Worker : BackgroundService 6 | { 7 | private readonly ILogger logger; 8 | private readonly IKubernetes kubernetesClient; 9 | 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// Inject in the constructor the IKubernetes interface. 13 | /// 14 | /// The logger instance used for logging information. 15 | /// The Kubernetes client used to interact with the Kubernetes API. 16 | public Worker(ILogger logger, IKubernetes kubernetesClient) 17 | { 18 | this.logger = logger; 19 | this.kubernetesClient = kubernetesClient; 20 | } 21 | 22 | protected override async Task ExecuteAsync(CancellationToken stoppingToken) 23 | { 24 | while (!stoppingToken.IsCancellationRequested) 25 | { 26 | logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); 27 | 28 | // Read the list of pods contained in default namespace 29 | var podList = kubernetesClient.CoreV1.ListNamespacedPod("default"); 30 | 31 | // Print pods names 32 | foreach (var pod in podList.Items) 33 | { 34 | Console.WriteLine(pod.Metadata.Name); 35 | } 36 | 37 | await Task.Delay(1000, stoppingToken).ConfigureAwait(false); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/workerServiceDependencyInjection/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/workerServiceDependencyInjection/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.Hosting.Lifetime": "Information" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/workerServiceDependencyInjection/workerServiceDependencyInjection.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | enable 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/yaml/Program.cs: -------------------------------------------------------------------------------- 1 | using k8s; 2 | using k8s.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | var typeMap = new Dictionary 7 | { 8 | { "v1/Pod", typeof(V1Pod) }, 9 | { "v1/Service", typeof(V1Service) }, 10 | { "apps/v1/Deployment", typeof(V1Deployment) }, 11 | }; 12 | 13 | var objects = await KubernetesYaml.LoadAllFromFileAsync(args[0], typeMap).ConfigureAwait(false); 14 | 15 | foreach (var obj in objects) 16 | { 17 | Console.WriteLine(obj); 18 | } 19 | -------------------------------------------------------------------------------- /examples/yaml/yaml.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | 5 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0.100", 4 | "rollForward": "latestMajor" 5 | }, 6 | "msbuild-sdks": { 7 | "Microsoft.Build.Traversal": "4.1.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /kubernetes-client.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kubernetes-client/csharp/8d0547bcff45b589aeecf4590683986c8581dbbb/logo.png -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/Global.cs: -------------------------------------------------------------------------------- 1 | global using k8s.Autorest; 2 | global using k8s.Models; 3 | global using System; 4 | global using System.Collections.Generic; 5 | global using System.IO; 6 | global using System.Linq; 7 | global using System.Text.Json; 8 | global using System.Text.Json.Serialization; 9 | global using System.Threading; 10 | global using System.Threading.Tasks; 11 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/AuthProvider.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Contains information that describes identity information. This is use to tell the kubernetes cluster who you are. 7 | /// 8 | [YamlSerializable] 9 | public class AuthProvider 10 | { 11 | /// 12 | /// Gets or sets the nickname for this auth provider. 13 | /// 14 | [YamlMember(Alias = "name")] 15 | public string Name { get; set; } 16 | 17 | /// 18 | /// Gets or sets the configuration for this auth provider 19 | /// 20 | [YamlMember(Alias = "config")] 21 | public Dictionary Config { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/Cluster.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Relates nicknames to cluster information. 7 | /// 8 | [YamlSerializable] 9 | public class Cluster 10 | { 11 | /// 12 | /// Gets or sets the cluster information. 13 | /// 14 | [YamlMember(Alias = "cluster")] 15 | public ClusterEndpoint ClusterEndpoint { get; set; } 16 | 17 | /// 18 | /// Gets or sets the nickname for this Cluster. 19 | /// 20 | [YamlMember(Alias = "name")] 21 | public string Name { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/ClusterEndpoint.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Contains information about how to communicate with a kubernetes cluster 7 | /// 8 | [YamlSerializable] 9 | public class ClusterEndpoint 10 | { 11 | /// 12 | /// Gets or sets the path to a cert file for the certificate authority. 13 | /// 14 | [YamlMember(Alias = "certificate-authority", ApplyNamingConventions = false)] 15 | public string CertificateAuthority { get; set; } 16 | 17 | /// 18 | /// Gets or sets =PEM-encoded certificate authority certificates. Overrides . 19 | /// 20 | [YamlMember(Alias = "certificate-authority-data", ApplyNamingConventions = false)] 21 | public string CertificateAuthorityData { get; set; } 22 | 23 | /// 24 | /// Gets or sets the address of the kubernetes cluster (https://hostname:port). 25 | /// 26 | [YamlMember(Alias = "server")] 27 | public string Server { get; set; } 28 | 29 | /// 30 | /// Gets or sets a value to override the TLS server name. 31 | /// 32 | [YamlMember(Alias = "tls-server-name", ApplyNamingConventions = false)] 33 | public string TlsServerName { get; set; } 34 | 35 | /// 36 | /// Gets or sets a value indicating whether to skip the validity check for the server's certificate. 37 | /// This will make your HTTPS connections insecure. 38 | /// 39 | [YamlMember(Alias = "insecure-skip-tls-verify", ApplyNamingConventions = false)] 40 | public bool SkipTlsVerify { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/Context.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Relates nicknames to context information. 7 | /// 8 | [YamlSerializable] 9 | public class Context 10 | { 11 | /// 12 | /// Gets or sets the context information. 13 | /// 14 | [YamlMember(Alias = "context")] 15 | public ContextDetails ContextDetails { get; set; } 16 | 17 | /// 18 | /// Gets or sets the nickname for this context. 19 | /// 20 | [YamlMember(Alias = "name")] 21 | public string Name { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/ContextDetails.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Represents a tuple of references to a cluster (how do I communicate with a kubernetes cluster), 7 | /// a user (how do I identify myself), and a namespace (what subset of resources do I want to work with) 8 | /// 9 | [YamlSerializable] 10 | public class ContextDetails 11 | { 12 | /// 13 | /// Gets or sets the name of the cluster for this context. 14 | /// 15 | [YamlMember(Alias = "cluster")] 16 | public string Cluster { get; set; } 17 | 18 | /// 19 | /// Gets or sets the name of the user for this context. 20 | /// 21 | [YamlMember(Alias = "user")] 22 | public string User { get; set; } 23 | 24 | /// 25 | /// /Gets or sets the default namespace to use on unspecified requests. 26 | /// 27 | [YamlMember(Alias = "namespace")] 28 | public string Namespace { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/ExecCredentialResponse.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | [YamlSerializable] 6 | public class ExecCredentialResponse 7 | { 8 | public class ExecStatus 9 | { 10 | #nullable enable 11 | public DateTime? ExpirationTimestamp { get; set; } 12 | public string? Token { get; set; } 13 | public string? ClientCertificateData { get; set; } 14 | public string? ClientKeyData { get; set; } 15 | #nullable disable 16 | 17 | public bool IsValid() 18 | { 19 | return !string.IsNullOrEmpty(Token) || 20 | (!string.IsNullOrEmpty(ClientCertificateData) && !string.IsNullOrEmpty(ClientKeyData)); 21 | } 22 | } 23 | 24 | [JsonPropertyName("apiVersion")] 25 | public string ApiVersion { get; set; } 26 | [JsonPropertyName("kind")] 27 | public string Kind { get; set; } 28 | [JsonPropertyName("status")] 29 | public ExecStatus Status { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/ExternalExecution.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | [YamlSerializable] 6 | public class ExternalExecution 7 | { 8 | [YamlMember(Alias = "apiVersion")] 9 | public string ApiVersion { get; set; } 10 | 11 | /// 12 | /// The command to execute. Required. 13 | /// 14 | [YamlMember(Alias = "command")] 15 | public string Command { get; set; } 16 | 17 | /// 18 | /// Environment variables to set when executing the plugin. Optional. 19 | /// 20 | [YamlMember(Alias = "env")] 21 | public IList> EnvironmentVariables { get; set; } 22 | 23 | /// 24 | /// Arguments to pass when executing the plugin. Optional. 25 | /// 26 | [YamlMember(Alias = "args")] 27 | public IList Arguments { get; set; } 28 | 29 | /// 30 | /// Text shown to the user when the executable doesn't seem to be present. Optional. 31 | /// 32 | [YamlMember(Alias = "installHint")] 33 | public string InstallHint { get; set; } 34 | 35 | /// 36 | /// Whether or not to provide cluster information to this exec plugin as a part of 37 | /// the KUBERNETES_EXEC_INFO environment variable. Optional. 38 | /// 39 | [YamlMember(Alias = "provideClusterInfo")] 40 | public bool ProvideClusterInfo { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/StaticContext.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels; 4 | 5 | [YamlStaticContext] 6 | public partial class StaticContext : YamlDotNet.Serialization.StaticContext 7 | { 8 | } -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/KubeConfigModels/User.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Relates nicknames to auth information. 7 | /// 8 | [YamlSerializable] 9 | public class User 10 | { 11 | /// 12 | /// Gets or sets the auth information. 13 | /// 14 | [YamlMember(Alias = "user")] 15 | public UserCredentials UserCredentials { get; set; } 16 | 17 | /// 18 | /// Gets or sets the nickname for this auth information. 19 | /// 20 | [YamlMember(Alias = "name")] 21 | public string Name { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/SourceGenerationContext.cs: -------------------------------------------------------------------------------- 1 | using static k8s.KubernetesJson; 2 | 3 | namespace k8s; 4 | 5 | [JsonSourceGenerationOptions( 6 | DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, 7 | PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, 8 | Converters = new[] { typeof(Iso8601TimeSpanConverter), typeof(KubernetesDateTimeConverter), typeof(KubernetesDateTimeOffsetConverter) }) 9 | ] 10 | internal partial class SourceGenerationContext : JsonSerializerContext 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /src/KubernetesClient.Aot/V1PatchJsonConverter.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | #pragma warning disable CA1812 // Avoid uninstantiated internal classes 4 | internal sealed class V1PatchJsonConverter : JsonConverter 5 | #pragma warning restore CA1812 // Avoid uninstantiated internal classes 6 | { 7 | public override V1Patch Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 8 | { 9 | throw new NotImplementedException(); 10 | } 11 | 12 | public override void Write(Utf8JsonWriter writer, V1Patch value, JsonSerializerOptions options) 13 | { 14 | if (writer == null) 15 | { 16 | throw new ArgumentNullException(nameof(writer)); 17 | } 18 | 19 | var content = value?.Content; 20 | if (content is string s) 21 | { 22 | writer.WriteRawValue(s); 23 | return; 24 | } 25 | 26 | throw new NotSupportedException("only string json patch is supported"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/KubernetesClient.Classic/Global.cs: -------------------------------------------------------------------------------- 1 | global using k8s.Autorest; 2 | global using k8s.Models; 3 | global using System; 4 | global using System.Collections.Generic; 5 | global using System.IO; 6 | global using System.Linq; 7 | global using System.Text.Json; 8 | global using System.Text.Json.Serialization; 9 | global using System.Threading; 10 | global using System.Threading.Tasks; 11 | -------------------------------------------------------------------------------- /src/KubernetesClient.Classic/Kubernetes.Websocket.Netstandard.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Security; 2 | using System.Security.Cryptography.X509Certificates; 3 | 4 | namespace k8s; 5 | 6 | public partial class Kubernetes 7 | { 8 | partial void BeforeRequest() 9 | { 10 | System.Net.ServicePointManager.ServerCertificateValidationCallback += ServerCertificateValidationCallback; 11 | } 12 | 13 | partial void AfterRequest() 14 | { 15 | System.Net.ServicePointManager.ServerCertificateValidationCallback -= ServerCertificateValidationCallback; 16 | } 17 | 18 | private bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, 19 | SslPolicyErrors sslPolicyErrors) 20 | { 21 | if (SkipTlsVerify) 22 | { 23 | return true; 24 | } 25 | 26 | return CertificateValidationCallBack(sender, CaCerts, certificate, chain, sslPolicyErrors); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Cordon.cs: -------------------------------------------------------------------------------- 1 | using Json.Patch; 2 | using k8s.Models; 3 | using System.Text.Json; 4 | 5 | namespace k8s.kubectl.beta; 6 | 7 | public partial class AsyncKubectl 8 | { 9 | public async Task Cordon(string nodeName, CancellationToken cancellationToken = default) 10 | { 11 | await PatchNodeUnschedulable(nodeName, true, cancellationToken).ConfigureAwait(false); 12 | } 13 | 14 | public async Task Uncordon(string nodeName, CancellationToken cancellationToken = default) 15 | { 16 | await PatchNodeUnschedulable(nodeName, false, cancellationToken).ConfigureAwait(false); 17 | } 18 | 19 | private async Task PatchNodeUnschedulable(string nodeName, bool desired, CancellationToken cancellationToken = default) 20 | { 21 | var node = await client.CoreV1.ReadNodeAsync(nodeName, cancellationToken: cancellationToken).ConfigureAwait(false); 22 | 23 | var old = JsonSerializer.SerializeToDocument(node); 24 | node.Spec.Unschedulable = desired; 25 | 26 | var patch = old.CreatePatch(node); 27 | 28 | await client.CoreV1.PatchNodeAsync(new V1Patch(patch, V1Patch.PatchType.JsonPatch), nodeName, cancellationToken: cancellationToken).ConfigureAwait(false); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Version.cs: -------------------------------------------------------------------------------- 1 | using k8s.Models; 2 | 3 | namespace k8s.kubectl.beta; 4 | 5 | public partial class AsyncKubectl 6 | { 7 | private const string AsssemblyVersion = ThisAssembly.AssemblyInformationalVersion; 8 | 9 | public record KubernetesSDKVersion 10 | { 11 | public string ClientVersion { get; init; } = AsssemblyVersion; 12 | 13 | public string ClientSwaggerVersion { get; init; } = GeneratedApiVersion.SwaggerVersion; 14 | 15 | public VersionInfo ServerVersion { get; init; } = default!; 16 | } 17 | 18 | public async Task Version(CancellationToken cancellationToken = default) 19 | { 20 | var serverVersion = await client.Version.GetCodeAsync(cancellationToken).ConfigureAwait(false); 21 | return new KubernetesSDKVersion { ServerVersion = serverVersion }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/KubernetesClient.Kubectl/Beta/AsyncKubectl.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.kubectl.beta; 2 | 3 | public partial class AsyncKubectl 4 | { 5 | private readonly IKubernetes client; 6 | 7 | public AsyncKubectl(IKubernetes client) 8 | { 9 | this.client = client; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/KubernetesClient.Kubectl/Beta/Kubectl.Cordon.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.kubectl.beta; 2 | 3 | public partial class Kubectl 4 | { 5 | public void Cordon(string nodeName) 6 | { 7 | client.Cordon(nodeName).GetAwaiter().GetResult(); 8 | } 9 | 10 | public void Uncordon(string nodeName) 11 | { 12 | client.Uncordon(nodeName).GetAwaiter().GetResult(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/KubernetesClient.Kubectl/Beta/Kubectl.Version.cs: -------------------------------------------------------------------------------- 1 | using static k8s.kubectl.beta.AsyncKubectl; 2 | 3 | namespace k8s.kubectl.beta; 4 | 5 | public partial class Kubectl 6 | { 7 | // TODO should auto generate this 8 | public KubernetesSDKVersion Version() 9 | { 10 | return client.Version().GetAwaiter().GetResult(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/KubernetesClient.Kubectl/Beta/Kubectl.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.kubectl.beta; 2 | 3 | public partial class Kubectl 4 | { 5 | private readonly AsyncKubectl client; 6 | 7 | public Kubectl(IKubernetes client) 8 | { 9 | this.client = new AsyncKubectl(client); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/KubernetesClient.Kubectl/KubernetesClient.Kubectl.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0;net9.0 5 | enable 6 | enable 7 | k8s.kubectl 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/KubernetesClient/Authentication/ExecTokenProvider.cs: -------------------------------------------------------------------------------- 1 | using k8s.KubeConfigModels; 2 | using System.Net.Http.Headers; 3 | 4 | namespace k8s.Authentication 5 | { 6 | public class ExecTokenProvider : ITokenProvider 7 | { 8 | private readonly ExternalExecution exec; 9 | private ExecCredentialResponse response; 10 | 11 | public ExecTokenProvider(ExternalExecution exec) 12 | { 13 | this.exec = exec; 14 | } 15 | 16 | private bool NeedsRefresh() 17 | { 18 | if (response?.Status == null) 19 | { 20 | return true; 21 | } 22 | 23 | if (response.Status.ExpirationTimestamp == null) 24 | { 25 | return false; 26 | } 27 | 28 | return DateTime.UtcNow.AddSeconds(30) > response.Status.ExpirationTimestamp; 29 | } 30 | 31 | public async Task GetAuthenticationHeaderAsync(CancellationToken cancellationToken) 32 | { 33 | if (NeedsRefresh()) 34 | { 35 | await RefreshToken().ConfigureAwait(false); 36 | } 37 | 38 | return new AuthenticationHeaderValue("Bearer", response.Status.Token); 39 | } 40 | 41 | private async Task RefreshToken() 42 | { 43 | response = 44 | await Task.Run(() => KubernetesClientConfiguration.ExecuteExternalCommand(this.exec)).ConfigureAwait(false); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/KubernetesClient/Authentication/ITokenProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System.Net.Http.Headers; 5 | 6 | #pragma warning disable SA1606 7 | #pragma warning disable SA1614 8 | namespace k8s.Authentication 9 | { 10 | /// 11 | /// Interface to a source of access tokens. 12 | /// 13 | public interface ITokenProvider 14 | { 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// AuthenticationHeaderValue 20 | Task GetAuthenticationHeaderAsync(CancellationToken cancellationToken); 21 | } 22 | } 23 | #pragma warning restore SA1614 24 | #pragma warning restore SA1606 25 | -------------------------------------------------------------------------------- /src/KubernetesClient/Authentication/ServiceClientCredentials.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System.Net.Http; 5 | 6 | namespace k8s.Authentication 7 | { 8 | /// 9 | /// ServiceClientCredentials is the abstraction for credentials used by ServiceClients accessing REST services. 10 | /// 11 | public abstract class ServiceClientCredentials 12 | { 13 | /// 14 | /// Apply the credentials to the HTTP request. 15 | /// 16 | /// The HTTP request message. 17 | /// Cancellation token. 18 | /// 19 | /// Task that will complete when processing has finished. 20 | /// 21 | public virtual Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken) 22 | { 23 | // Return an empty task by default 24 | return Task.CompletedTask; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/KubernetesClient/Authentication/StringTokenProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System.Net.Http.Headers; 5 | 6 | namespace k8s.Authentication 7 | { 8 | /// 9 | /// A simple token provider that always provides a static access token. 10 | /// 11 | public sealed class StringTokenProvider : ITokenProvider 12 | { 13 | private readonly string _accessToken; 14 | private readonly string _type; 15 | 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// Create a token provider for the given token type that returns the given 19 | /// access token. 20 | /// 21 | /// The access token to return. 22 | /// The token type of the given access token. 23 | public StringTokenProvider(string accessToken, string tokenType) 24 | { 25 | _accessToken = accessToken; 26 | _type = tokenType; 27 | } 28 | 29 | /// 30 | /// Gets the token type of this access token. 31 | /// 32 | public string TokenType => _type; 33 | 34 | /// 35 | /// Returns the static access token. 36 | /// 37 | /// The cancellation token for this action. 38 | /// This will not be used since the returned token is static. 39 | /// The access token. 40 | public Task GetAuthenticationHeaderAsync(CancellationToken cancellationToken) 41 | { 42 | return Task.FromResult(new AuthenticationHeaderValue(_type, _accessToken)); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/KubernetesClient/Autorest/HttpExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System.Net.Http; 5 | using System.Net.Http.Headers; 6 | 7 | namespace k8s.Autorest 8 | { 9 | /// 10 | /// Extensions for manipulating HTTP request and response objects. 11 | /// 12 | internal static class HttpExtensions 13 | { 14 | /// 15 | /// Get the content headers of an HttpRequestMessage. 16 | /// 17 | /// The request message. 18 | /// The content headers. 19 | public static HttpHeaders GetContentHeaders(this HttpRequestMessage request) 20 | { 21 | return request?.Content?.Headers; 22 | } 23 | 24 | /// 25 | /// Get the content headers of an HttpResponseMessage. 26 | /// 27 | /// The response message. 28 | /// The content headers. 29 | public static HttpHeaders GetContentHeaders(this HttpResponseMessage response) 30 | { 31 | return response?.Content?.Headers; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/KubernetesClient/Autorest/HttpRequestMessageWrapper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System.Net.Http; 5 | 6 | namespace k8s.Autorest 7 | { 8 | /// 9 | /// Wrapper around HttpRequestMessage type that copies properties of HttpRequestMessage so that 10 | /// they are available after the HttpClient gets disposed. 11 | /// 12 | public class HttpRequestMessageWrapper : HttpMessageWrapper 13 | { 14 | /// 15 | /// Initializes a new instance of the class from HttpRequestMessage. 16 | /// and content. 17 | /// 18 | #pragma warning disable SA1611 // Element parameters should be documented 19 | public HttpRequestMessageWrapper(HttpRequestMessage httpRequest, string content) 20 | #pragma warning restore SA1611 // Element parameters should be documented 21 | { 22 | if (httpRequest == null) 23 | { 24 | throw new ArgumentNullException("httpRequest"); 25 | } 26 | 27 | CopyHeaders(httpRequest.Headers); 28 | CopyHeaders(httpRequest.GetContentHeaders()); 29 | 30 | Content = content; 31 | Method = httpRequest.Method; 32 | RequestUri = httpRequest.RequestUri; 33 | } 34 | 35 | /// 36 | /// Gets or sets the HTTP method used by the HTTP request message. 37 | /// 38 | public HttpMethod Method { get; protected set; } 39 | 40 | /// 41 | /// Gets or sets the Uri used for the HTTP request. 42 | /// 43 | public Uri RequestUri { get; protected set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/KubernetesClient/Autorest/HttpResponseMessageWrapper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT License. See License.txt in the project root for license information. 3 | 4 | using System.Net; 5 | using System.Net.Http; 6 | 7 | namespace k8s.Autorest 8 | { 9 | /// 10 | /// Wrapper around HttpResponseMessage type that copies properties of HttpResponseMessage so that 11 | /// they are available after the HttpClient gets disposed. 12 | /// 13 | public class HttpResponseMessageWrapper : HttpMessageWrapper 14 | { 15 | /// 16 | /// Initializes a new instance of the class from HttpResponseMessage. 17 | /// and content. 18 | /// 19 | #pragma warning disable SA1611 // Element parameters should be documented 20 | public HttpResponseMessageWrapper(HttpResponseMessage httpResponse, string content) 21 | #pragma warning restore SA1611 // Element parameters should be documented 22 | { 23 | if (httpResponse == null) 24 | { 25 | throw new ArgumentNullException("httpResponse"); 26 | } 27 | 28 | CopyHeaders(httpResponse.Headers); 29 | CopyHeaders(httpResponse.GetContentHeaders()); 30 | 31 | Content = content; 32 | StatusCode = httpResponse.StatusCode; 33 | ReasonPhrase = httpResponse.ReasonPhrase; 34 | } 35 | 36 | /// 37 | /// Gets or sets the status code of the HTTP response. 38 | /// 39 | public HttpStatusCode StatusCode { get; protected set; } 40 | 41 | /// 42 | /// Exposes the reason phrase, typically sent along with the status code. 43 | /// 44 | public string ReasonPhrase { get; protected set; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/KubernetesClient/ChannelIndex.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// These values identify the various channels which you can use when interacting with a process running in a container in a Kubernetes 5 | /// pod. 6 | /// 7 | /// 8 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "byte only")] 9 | public enum ChannelIndex : byte 10 | { 11 | /// 12 | /// The standard input channel. Use this channel to send input to a process running in a container inside a Kubernetes pod. 13 | /// 14 | StdIn, 15 | 16 | /// 17 | /// The standard output channel. Use this channel to read standard output generated by a process running in a container in a Kubernetes pod. 18 | /// 19 | StdOut, 20 | 21 | /// 22 | /// The standard error channel. Use this channel to read the error output generated by a process running in a container in a Kubernetes pod. 23 | /// 24 | StdErr, 25 | 26 | /// 27 | /// The error channel. This channel is used by Kubernetes to send you error messages, including the exit code of the process. 28 | /// 29 | Error, 30 | 31 | /// 32 | /// The resize channel. Use this channel to resize the terminal. You need to send a JSON-formatted object over this channel, which 33 | /// has a Width and Height property. 34 | /// 35 | /// 36 | Resize, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/KubernetesClient/ClientSets/ClientSet.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.ClientSets 2 | { 3 | /// 4 | /// Represents a base class for clients that interact with Kubernetes resources. 5 | /// Provides shared functionality for derived resource-specific clients. 6 | /// 7 | public partial class ClientSet 8 | { 9 | private readonly Kubernetes _kubernetes; 10 | 11 | public ClientSet(Kubernetes kubernetes) 12 | { 13 | _kubernetes = kubernetes; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/KubernetesClient/ClientSets/ResourceClient.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.ClientSets 2 | { 3 | /// 4 | /// Represents a set of Kubernetes clients for interacting with the Kubernetes API. 5 | /// This class provides access to various client implementations for managing Kubernetes resources. 6 | /// 7 | public abstract class ResourceClient 8 | { 9 | protected Kubernetes Client { get; } 10 | 11 | public ResourceClient(Kubernetes kubernetes) 12 | { 13 | Client = kubernetes; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/KubernetesClient/Exceptions/KubeConfigException.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Exceptions 2 | { 3 | /// 4 | /// The exception that is thrown when the kube config is invalid 5 | /// 6 | public class KubeConfigException : Exception 7 | { 8 | public KubeConfigException() 9 | { 10 | } 11 | 12 | public KubeConfigException(string message) 13 | : base(message) 14 | { 15 | } 16 | 17 | public KubeConfigException(string message, Exception inner) 18 | : base(message, inner) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/KubernetesClient/Exceptions/KubernetesClientException.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Exceptions 2 | { 3 | /// 4 | /// The exception that is thrown when there is a client exception 5 | /// 6 | public class KubernetesClientException : Exception 7 | { 8 | public KubernetesClientException() 9 | { 10 | } 11 | 12 | public KubernetesClientException(string message) 13 | : base(message) 14 | { 15 | } 16 | 17 | public KubernetesClientException(string message, Exception inner) 18 | : base(message, inner) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/KubernetesClient/ExecAsyncCallback.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// A prototype for a callback which asynchronously processes the standard input, standard output and standard error of a command executing in 5 | /// a container. 6 | /// 7 | /// 8 | /// The standard input stream of the process. 9 | /// 10 | /// 11 | /// The standard output stream of the process. 12 | /// 13 | /// 14 | /// The standard error stream of the remote process. 15 | /// 16 | /// 17 | /// A which represents the asynchronous processing of the process input, output and error streams. This task 18 | /// should complete once you're done interacting with the remote process. 19 | /// 20 | public delegate Task ExecAsyncCallback(Stream stdIn, Stream stdOut, Stream stdErr); 21 | } 22 | -------------------------------------------------------------------------------- /src/KubernetesClient/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace k8s 5 | { 6 | public static class Extensions 7 | { 8 | public static KubernetesEntityAttribute GetKubernetesTypeMetadata(this T obj) 9 | where T : IKubernetesObject 10 | => 11 | obj.GetType().GetKubernetesTypeMetadata(); 12 | public static KubernetesEntityAttribute GetKubernetesTypeMetadata(this Type currentType) 13 | { 14 | var attr = currentType.GetCustomAttribute(); 15 | if (attr == null) 16 | { 17 | throw new InvalidOperationException($"Custom resource must have {nameof(KubernetesEntityAttribute)} applied to it"); 18 | } 19 | 20 | return attr; 21 | } 22 | 23 | public static T Initialize(this T obj) 24 | where T : IKubernetesObject 25 | { 26 | var metadata = obj.GetKubernetesTypeMetadata(); 27 | obj.ApiVersion = !string.IsNullOrEmpty(metadata.Group) ? $"{metadata.Group}/{metadata.ApiVersion}" : metadata.ApiVersion; 28 | obj.Kind = metadata.Kind ?? obj.GetType().Name; 29 | if (obj is IMetadata withMetadata && withMetadata.Metadata == null) 30 | { 31 | withMetadata.Metadata = new V1ObjectMeta(); 32 | } 33 | 34 | return obj; 35 | } 36 | 37 | internal static bool IsValidKubernetesName(this string value) => !Regex.IsMatch(value, "^[a-z0-9-]+$"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/KubernetesClient/FileSystem.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | internal static class FileSystem 4 | { 5 | public interface IFileSystem 6 | { 7 | Stream OpenRead(string path); 8 | 9 | bool Exists(string path); 10 | 11 | string ReadAllText(string path); 12 | } 13 | 14 | public static IFileSystem Current { get; private set; } = new RealFileSystem(); 15 | 16 | public static IDisposable With(IFileSystem fileSystem) 17 | { 18 | return new InjectedFileSystem(fileSystem); 19 | } 20 | 21 | private class InjectedFileSystem : IDisposable 22 | { 23 | private readonly IFileSystem _original; 24 | 25 | public InjectedFileSystem(IFileSystem fileSystem) 26 | { 27 | _original = Current; 28 | Current = fileSystem; 29 | } 30 | 31 | public void Dispose() 32 | { 33 | Current = _original; 34 | } 35 | } 36 | 37 | private class RealFileSystem : IFileSystem 38 | { 39 | public bool Exists(string path) 40 | { 41 | return File.Exists(path); 42 | } 43 | 44 | public Stream OpenRead(string path) 45 | { 46 | return File.OpenRead(path); 47 | } 48 | 49 | public string ReadAllText(string path) 50 | { 51 | return File.ReadAllText(path); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/KubernetesClient/FloatEmitter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using YamlDotNet.Core; 3 | using YamlDotNet.Core.Events; 4 | using YamlDotNet.Serialization; 5 | using YamlDotNet.Serialization.EventEmitters; 6 | 7 | namespace k8s 8 | { 9 | internal class FloatEmitter : ChainedEventEmitter 10 | { 11 | public FloatEmitter(IEventEmitter nextEmitter) 12 | : base(nextEmitter) 13 | { 14 | } 15 | 16 | public override void Emit(ScalarEventInfo eventInfo, IEmitter emitter) 17 | { 18 | switch (eventInfo.Source.Value) 19 | { 20 | // Floating point numbers should always render at least one zero (e.g. 1.0f => '1.0' not '1') 21 | case double d: 22 | emitter.Emit(new Scalar(d.ToString("0.0######################", CultureInfo.InvariantCulture))); 23 | break; 24 | case float f: 25 | emitter.Emit(new Scalar(f.ToString("0.0######################", CultureInfo.InvariantCulture))); 26 | break; 27 | default: 28 | base.Emit(eventInfo, emitter); 29 | break; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/KubernetesClient/GeneratedApiVersion.cs: -------------------------------------------------------------------------------- 1 | namespace k8s; 2 | 3 | public static class GeneratedApiVersion 4 | { 5 | // Now API version is the same as model version 6 | // Change this if api is generated from a separate swagger spec 7 | 8 | public const string AssemblyVersion = GeneratedModelVersion.AssemblyVersion; 9 | public const string SwaggerVersion = GeneratedModelVersion.SwaggerVersion; 10 | } 11 | -------------------------------------------------------------------------------- /src/KubernetesClient/Global.cs: -------------------------------------------------------------------------------- 1 | global using k8s.Autorest; 2 | global using k8s.Models; 3 | global using System; 4 | global using System.Collections.Generic; 5 | global using System.IO; 6 | global using System.Linq; 7 | global using System.Text.Json; 8 | global using System.Text.Json.Serialization; 9 | global using System.Threading; 10 | global using System.Threading.Tasks; 11 | -------------------------------------------------------------------------------- /src/KubernetesClient/IItems.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// Kubernetes object that exposes list of objects 5 | /// 6 | /// type of the objects 7 | public interface IItems 8 | { 9 | /// 10 | /// Gets or sets list of objects. More info: 11 | /// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md 12 | /// 13 | IList Items { get; set; } 14 | } 15 | 16 | public static class ItemsExt 17 | { 18 | public static IEnumerator GetEnumerator(this IItems items) 19 | { 20 | if (items is null) 21 | { 22 | throw new ArgumentNullException(nameof(items)); 23 | } 24 | 25 | return items.Items.GetEnumerator(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/KubernetesClient/IKubernetes.Exec.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | public partial interface IKubernetes 4 | { 5 | /// 6 | /// Executes a command in a container in a pod. 7 | /// 8 | /// 9 | /// The name of the pod which contains the container in which to execute the command. 10 | /// 11 | /// 12 | /// The namespace of the container. 13 | /// 14 | /// 15 | /// The container in which to run the command. 16 | /// 17 | /// 18 | /// The command to execute. 19 | /// 20 | /// 21 | /// if allocate a pseudo-TTY 22 | /// 23 | /// 24 | /// A callback which processes the standard input, standard output and standard error. 25 | /// 26 | /// 27 | /// A which can be used to cancel the asynchronous operation. 28 | /// 29 | /// 30 | /// A which represents the asynchronous operation. 31 | /// 32 | Task NamespacedPodExecAsync(string name, string @namespace, string container, IEnumerable command, 33 | bool tty, ExecAsyncCallback action, CancellationToken cancellationToken); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/KubernetesClient/IKubernetes.cs: -------------------------------------------------------------------------------- 1 | namespace k8s; 2 | 3 | public partial interface IKubernetes : IBasicKubernetes, IDisposable 4 | { 5 | /// 6 | /// The base URI of the service. 7 | /// 8 | Uri BaseUri { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/KubernetesClient/IKubernetesObject.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// Represents a generic Kubernetes object. 5 | /// 6 | /// 7 | /// You can use the if you receive JSON from a Kubernetes API server but 8 | /// are unsure which object the API server is about to return. You can parse the JSON as a 9 | /// and use the and properties to get basic metadata about any Kubernetes object. 10 | /// You can then 11 | /// 12 | public interface IKubernetesObject 13 | { 14 | /// 15 | /// Gets or sets aPIVersion defines the versioned schema of this 16 | /// representation of an object. Servers should convert recognized 17 | /// schemas to the latest internal value, and may reject unrecognized 18 | /// values. More info: 19 | /// https://git.k8s.io/community/contributors/devel/api-conventions.md#resources 20 | /// 21 | [JsonPropertyName("apiVersion")] 22 | string ApiVersion { get; set; } 23 | 24 | /// 25 | /// Gets or sets kind is a string value representing the REST resource 26 | /// this object represents. Servers may infer this from the endpoint 27 | /// the client submits requests to. Cannot be updated. In CamelCase. 28 | /// More info: 29 | /// https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds 30 | /// 31 | [JsonPropertyName("kind")] 32 | string Kind { get; set; } 33 | } 34 | 35 | /// Represents a generic Kubernetes object that has an API version, a kind, and metadata. 36 | /// type of metadata 37 | public interface IKubernetesObject : IKubernetesObject, IMetadata 38 | { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/KubernetesClient/IMetadata.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// Kubernetes object that exposes metadata 5 | /// 6 | /// Type of metadata exposed. Usually this will be either 7 | /// for lists or for objects 8 | public interface IMetadata 9 | { 10 | /// 11 | /// Gets or sets standard object's metadata. More info: 12 | /// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 13 | /// 14 | T Metadata { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/KubernetesClient/ISpec.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// Represents a Kubernetes object that has a spec 5 | /// 6 | /// type of Kubernetes object 7 | public interface ISpec 8 | { 9 | /// 10 | /// Gets or sets specification of the desired behavior of the entity. More 11 | /// info: 12 | /// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status 13 | /// 14 | T Spec { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/KubernetesClient/IStatus.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// Kubernetes object that exposes status 5 | /// 6 | /// The type of status object 7 | public interface IStatus 8 | { 9 | /// 10 | /// Gets or sets most recently observed status of the object. This data 11 | /// may not be up to date. Populated by the system. Read-only. More 12 | /// info: 13 | /// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status 14 | /// 15 | T Status { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/KubernetesClient/IValidate.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// Object that allows self validation 5 | /// 6 | public interface IValidate 7 | { 8 | /// 9 | /// Validate the object. 10 | /// 11 | void Validate(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/AuthProvider.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Contains information that describes identity information. This is use to tell the kubernetes cluster who you are. 7 | /// 8 | public class AuthProvider 9 | { 10 | /// 11 | /// Gets or sets the nickname for this auth provider. 12 | /// 13 | [YamlMember(Alias = "name")] 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// Gets or sets the configuration for this auth provider 18 | /// 19 | [YamlMember(Alias = "config")] 20 | public Dictionary Config { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/Cluster.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Relates nicknames to cluster information. 7 | /// 8 | public class Cluster 9 | { 10 | /// 11 | /// Gets or sets the cluster information. 12 | /// 13 | [YamlMember(Alias = "cluster")] 14 | public ClusterEndpoint ClusterEndpoint { get; set; } 15 | 16 | /// 17 | /// Gets or sets the nickname for this Cluster. 18 | /// 19 | [YamlMember(Alias = "name")] 20 | public string Name { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/Context.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Relates nicknames to context information. 7 | /// 8 | public class Context 9 | { 10 | /// 11 | /// Gets or sets the context information. 12 | /// 13 | [YamlMember(Alias = "context")] 14 | public ContextDetails ContextDetails { get; set; } 15 | 16 | /// 17 | /// Gets or sets the nickname for this context. 18 | /// 19 | [YamlMember(Alias = "name")] 20 | public string Name { get; set; } 21 | 22 | /// 23 | /// Gets or sets additional information. This is useful for extenders so that reads and writes don't clobber unknown fields. 24 | /// 25 | [YamlMember(Alias = "extensions")] 26 | public IEnumerable Extensions { get; set; } 27 | 28 | 29 | [Obsolete("This property is not set by the YAML config. Use ContextDetails.Namespace instead.")] 30 | [YamlMember(Alias = "namespace")] 31 | public string Namespace { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/ContextDetails.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Represents a tuple of references to a cluster (how do I communicate with a kubernetes cluster), 7 | /// a user (how do I identify myself), and a namespace (what subset of resources do I want to work with) 8 | /// 9 | public class ContextDetails 10 | { 11 | /// 12 | /// Gets or sets the name of the cluster for this context. 13 | /// 14 | [YamlMember(Alias = "cluster")] 15 | public string Cluster { get; set; } 16 | 17 | /// 18 | /// Gets or sets the name of the user for this context. 19 | /// 20 | [YamlMember(Alias = "user")] 21 | public string User { get; set; } 22 | 23 | /// 24 | /// /Gets or sets the default namespace to use on unspecified requests. 25 | /// 26 | [YamlMember(Alias = "namespace")] 27 | public string Namespace { get; set; } 28 | 29 | /// 30 | /// Gets or sets additional information. This is useful for extenders so that reads and writes don't clobber unknown fields. 31 | /// 32 | [YamlMember(Alias = "extensions")] 33 | public IEnumerable Extensions { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/ExecCredentialResponse.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.KubeConfigModels 2 | { 3 | public class ExecCredentialResponse 4 | { 5 | public class ExecStatus 6 | { 7 | #nullable enable 8 | public DateTime? ExpirationTimestamp { get; set; } 9 | public string? Token { get; set; } 10 | public string? ClientCertificateData { get; set; } 11 | public string? ClientKeyData { get; set; } 12 | #nullable disable 13 | 14 | public bool IsValid() 15 | { 16 | return !string.IsNullOrEmpty(Token) || 17 | (!string.IsNullOrEmpty(ClientCertificateData) && !string.IsNullOrEmpty(ClientKeyData)); 18 | } 19 | } 20 | 21 | [JsonPropertyName("apiVersion")] 22 | public string ApiVersion { get; set; } 23 | [JsonPropertyName("kind")] 24 | public string Kind { get; set; } 25 | [JsonPropertyName("status")] 26 | public ExecStatus Status { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/ExternalExecution.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | public class ExternalExecution 6 | { 7 | [YamlMember(Alias = "apiVersion")] 8 | public string ApiVersion { get; set; } 9 | 10 | /// 11 | /// The command to execute. Required. 12 | /// 13 | [YamlMember(Alias = "command")] 14 | public string Command { get; set; } 15 | 16 | /// 17 | /// Environment variables to set when executing the plugin. Optional. 18 | /// 19 | [YamlMember(Alias = "env")] 20 | public IList> EnvironmentVariables { get; set; } 21 | 22 | /// 23 | /// Arguments to pass when executing the plugin. Optional. 24 | /// 25 | [YamlMember(Alias = "args")] 26 | public IList Arguments { get; set; } 27 | 28 | /// 29 | /// Text shown to the user when the executable doesn't seem to be present. Optional. 30 | /// 31 | [YamlMember(Alias = "installHint")] 32 | public string InstallHint { get; set; } 33 | 34 | /// 35 | /// Whether or not to provide cluster information to this exec plugin as a part of 36 | /// the KUBERNETES_EXEC_INFO environment variable. Optional. 37 | /// 38 | [YamlMember(Alias = "provideClusterInfo")] 39 | public bool ProvideClusterInfo { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/NamedExtension.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// relates nicknames to extension information 7 | /// 8 | public class NamedExtension 9 | { 10 | /// 11 | /// Gets or sets the nickname for this extension. 12 | /// 13 | [YamlMember(Alias = "name")] 14 | public string Name { get; set; } 15 | 16 | /// 17 | /// Get or sets the extension information. 18 | /// 19 | [YamlMember(Alias = "extension")] 20 | public dynamic Extension { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubeConfigModels/User.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Serialization; 2 | 3 | namespace k8s.KubeConfigModels 4 | { 5 | /// 6 | /// Relates nicknames to auth information. 7 | /// 8 | public class User 9 | { 10 | /// 11 | /// Gets or sets the auth information. 12 | /// 13 | [YamlMember(Alias = "user")] 14 | public UserCredentials UserCredentials { get; set; } 15 | 16 | /// 17 | /// Gets or sets the nickname for this auth information. 18 | /// 19 | [YamlMember(Alias = "name")] 20 | public string Name { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubernetesClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0;net9.0 5 | k8s 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/KubernetesClient/KubernetesObject.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// Represents a generic Kubernetes object. 5 | /// 6 | /// 7 | /// You can use the if you receive JSON from a Kubernetes API server but 8 | /// are unsure which object the API server is about to return. You can parse the JSON as a 9 | /// and use the and properties to get basic metadata about any Kubernetes object. 10 | /// You can then 11 | /// 12 | public class KubernetesObject : IKubernetesObject 13 | { 14 | /// 15 | /// Gets or sets aPIVersion defines the versioned schema of this 16 | /// representation of an object. Servers should convert recognized 17 | /// schemas to the latest internal value, and may reject unrecognized 18 | /// values. More info: 19 | /// https://git.k8s.io/community/contributors/devel/api-conventions.md#resources 20 | /// 21 | [JsonPropertyName("apiVersion")] 22 | public string ApiVersion { get; set; } 23 | 24 | /// 25 | /// Gets or sets kind is a string value representing the REST resource 26 | /// this object represents. Servers may infer this from the endpoint 27 | /// the client submits requests to. Cannot be updated. In CamelCase. 28 | /// More info: 29 | /// https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds 30 | /// 31 | [JsonPropertyName("kind")] 32 | public string Kind { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/KubernetesClient/LeaderElection/ILock.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.LeaderElection 2 | { 3 | /// 4 | /// ILock offers a common interface for locking on arbitrary resources used in leader election. The Interface is used to hide the details on specific implementations in order to allow them to change over time. 5 | /// 6 | public interface ILock 7 | { 8 | /// 9 | /// Get returns the LeaderElectionRecord 10 | /// 11 | /// token to cancel the task 12 | /// the record 13 | Task GetAsync(CancellationToken cancellationToken = default); 14 | 15 | /// 16 | /// Create attempts to create a LeaderElectionRecord 17 | /// 18 | /// record to create 19 | /// token to cancel the task 20 | /// true if created 21 | Task CreateAsync(LeaderElectionRecord record, CancellationToken cancellationToken = default); 22 | 23 | /// 24 | /// Update will update and existing LeaderElectionRecord 25 | /// 26 | /// record to create 27 | /// token to cancel the task 28 | /// true if updated 29 | Task UpdateAsync(LeaderElectionRecord record, CancellationToken cancellationToken = default); 30 | 31 | 32 | /// 33 | /// the locks Identity 34 | /// 35 | string Identity { get; } 36 | 37 | /// 38 | /// Describe is used to convert details on current resource lock into a string 39 | /// 40 | /// resource lock description 41 | string Describe(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/KubernetesClient/LeaderElection/LeaderElectionConfig.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.LeaderElection 2 | { 3 | public class LeaderElectionConfig 4 | { 5 | public ILock Lock { get; set; } 6 | 7 | public TimeSpan LeaseDuration { get; set; } = TimeSpan.FromSeconds(15); 8 | 9 | public TimeSpan RenewDeadline { get; set; } = TimeSpan.FromSeconds(10); 10 | 11 | public TimeSpan RetryPeriod { get; set; } = TimeSpan.FromSeconds(2); 12 | 13 | public LeaderElectionConfig(ILock @lock) 14 | { 15 | Lock = @lock; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/KubernetesClient/LeaderElection/ResourceLock/ConfigMapLock.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.LeaderElection.ResourceLock 2 | { 3 | public class ConfigMapLock : MetaObjectAnnotationLock 4 | { 5 | public ConfigMapLock(IKubernetes client, string @namespace, string name, string identity) 6 | : base(client, @namespace, name, identity) 7 | { 8 | } 9 | 10 | protected override Task ReadMetaObjectAsync(IKubernetes client, string name, 11 | string namespaceParameter, 12 | CancellationToken cancellationToken) 13 | { 14 | if (client is null) 15 | { 16 | throw new ArgumentNullException(nameof(client)); 17 | } 18 | 19 | return client.CoreV1.ReadNamespacedConfigMapAsync(name, namespaceParameter, cancellationToken: cancellationToken); 20 | } 21 | 22 | protected override Task CreateMetaObjectAsync(IKubernetes client, V1ConfigMap obj, 23 | string namespaceParameter, 24 | CancellationToken cancellationToken) 25 | { 26 | if (client is null) 27 | { 28 | throw new ArgumentNullException(nameof(client)); 29 | } 30 | 31 | return client.CoreV1.CreateNamespacedConfigMapAsync(obj, namespaceParameter, cancellationToken: cancellationToken); 32 | } 33 | 34 | protected override Task ReplaceMetaObjectAsync(IKubernetes client, V1ConfigMap obj, string name, 35 | string namespaceParameter, 36 | CancellationToken cancellationToken) 37 | { 38 | if (client is null) 39 | { 40 | throw new ArgumentNullException(nameof(client)); 41 | } 42 | 43 | return client.CoreV1.ReplaceNamespacedConfigMapAsync(obj, name, namespaceParameter, cancellationToken: cancellationToken); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/KubernetesClient/LeaderElection/ResourceLock/EndpointsLock.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.LeaderElection.ResourceLock 2 | { 3 | public class EndpointsLock : MetaObjectAnnotationLock 4 | { 5 | public EndpointsLock(IKubernetes client, string @namespace, string name, string identity) 6 | : base(client, @namespace, name, identity) 7 | { 8 | } 9 | 10 | protected override Task ReadMetaObjectAsync(IKubernetes client, string name, string namespaceParameter, CancellationToken cancellationToken) 11 | { 12 | if (client is null) 13 | { 14 | throw new ArgumentNullException(nameof(client)); 15 | } 16 | 17 | return client.CoreV1.ReadNamespacedEndpointsAsync(name, namespaceParameter, cancellationToken: cancellationToken); 18 | } 19 | 20 | protected override Task CreateMetaObjectAsync(IKubernetes client, V1Endpoints obj, string namespaceParameter, 21 | CancellationToken cancellationToken) 22 | { 23 | if (client is null) 24 | { 25 | throw new ArgumentNullException(nameof(client)); 26 | } 27 | 28 | return client.CoreV1.CreateNamespacedEndpointsAsync(obj, namespaceParameter, cancellationToken: cancellationToken); 29 | } 30 | 31 | protected override Task ReplaceMetaObjectAsync(IKubernetes client, V1Endpoints obj, string name, string namespaceParameter, 32 | CancellationToken cancellationToken) 33 | { 34 | if (client is null) 35 | { 36 | throw new ArgumentNullException(nameof(client)); 37 | } 38 | 39 | return client.CoreV1.ReplaceNamespacedEndpointsAsync(obj, name, namespaceParameter, cancellationToken: cancellationToken); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/KubernetesClient/LeaderElection/ResourceLock/MetaObjectAnnotationLock.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.LeaderElection.ResourceLock 2 | { 3 | public abstract class MetaObjectAnnotationLock : MetaObjectLock 4 | where T : class, IMetadata, new() 5 | { 6 | protected MetaObjectAnnotationLock(IKubernetes client, string @namespace, string name, string identity) 7 | : base(client, @namespace, name, identity) 8 | { 9 | } 10 | 11 | private const string LeaderElectionRecordAnnotationKey = "control-plane.alpha.kubernetes.io/leader"; 12 | 13 | protected override LeaderElectionRecord GetLeaderElectionRecord(T obj) 14 | { 15 | var recordRawStringContent = obj.GetAnnotation(LeaderElectionRecordAnnotationKey); 16 | 17 | if (string.IsNullOrEmpty(recordRawStringContent)) 18 | { 19 | return new LeaderElectionRecord(); 20 | } 21 | 22 | var record = KubernetesJson.Deserialize(recordRawStringContent); 23 | return record; 24 | } 25 | 26 | 27 | protected override T SetLeaderElectionRecord(LeaderElectionRecord record, T metaObj) 28 | { 29 | metaObj.SetAnnotation(LeaderElectionRecordAnnotationKey, KubernetesJson.Serialize(record)); 30 | return metaObj; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/KubernetesClient/LeaderElection/ResourceLock/MultiLock.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.LeaderElection.ResourceLock 2 | { 3 | public class MultiLock : ILock 4 | { 5 | private readonly ILock primary; 6 | private readonly ILock secondary; 7 | 8 | public MultiLock(ILock primary, ILock secondary) 9 | { 10 | this.primary = primary; 11 | this.secondary = secondary; 12 | } 13 | 14 | public Task GetAsync(CancellationToken cancellationToken = default) 15 | { 16 | return primary.GetAsync(cancellationToken); 17 | } 18 | 19 | public async Task CreateAsync(LeaderElectionRecord record, CancellationToken cancellationToken = default) 20 | { 21 | return await primary.CreateAsync(record, cancellationToken).ConfigureAwait(false) 22 | && await secondary.CreateAsync(record, cancellationToken).ConfigureAwait(false); 23 | } 24 | 25 | public async Task UpdateAsync(LeaderElectionRecord record, CancellationToken cancellationToken = default) 26 | { 27 | return await primary.UpdateAsync(record, cancellationToken).ConfigureAwait(false) 28 | && await secondary.UpdateAsync(record, cancellationToken).ConfigureAwait(false); 29 | } 30 | 31 | public string Identity => primary.Identity; 32 | 33 | public string Describe() 34 | { 35 | return primary.Describe(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/ContainerMetrics.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | /// 4 | /// Describes the resource usage metrics of a container pull from metrics server API. 5 | /// 6 | public class ContainerMetrics 7 | { 8 | /// 9 | /// Defines container name corresponding to the one from pod.spec.containers. 10 | /// 11 | [JsonPropertyName("name")] 12 | public string Name { get; set; } 13 | 14 | /// 15 | /// The resource usage. 16 | /// 17 | [JsonPropertyName("usage")] 18 | public IDictionary Usage { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/GeneratedModelVersion.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models; 2 | 3 | public static class GeneratedModelVersion 4 | { 5 | public const string AssemblyVersion = ThisAssembly.AssemblyInformationalVersion; 6 | public const string SwaggerVersion = ThisAssembly.KubernetesSwaggerVersion; 7 | } 8 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/IntOrStringJsonConverter.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | internal sealed class IntOrStringJsonConverter : JsonConverter 4 | { 5 | public override IntstrIntOrString Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 6 | { 7 | switch (reader.TokenType) 8 | { 9 | case JsonTokenType.String: 10 | return reader.GetString(); 11 | case JsonTokenType.Number: 12 | return reader.GetInt64(); 13 | default: 14 | break; 15 | } 16 | 17 | throw new NotSupportedException(); 18 | } 19 | 20 | public override void Write(Utf8JsonWriter writer, IntstrIntOrString value, JsonSerializerOptions options) 21 | { 22 | if (writer == null) 23 | { 24 | throw new ArgumentNullException(nameof(writer)); 25 | } 26 | 27 | var s = value?.Value; 28 | 29 | if (long.TryParse(s, out var intv)) 30 | { 31 | writer.WriteNumberValue(intv); 32 | return; 33 | } 34 | 35 | writer.WriteStringValue(s); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/IntOrStringYamlConverter.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Core; 2 | using YamlDotNet.Serialization; 3 | 4 | namespace k8s.Models 5 | { 6 | public class IntOrStringYamlConverter : IYamlTypeConverter 7 | { 8 | public bool Accepts(Type type) 9 | { 10 | return type == typeof(IntstrIntOrString); 11 | } 12 | 13 | public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) 14 | { 15 | if (parser?.Current is YamlDotNet.Core.Events.Scalar scalar) 16 | { 17 | try 18 | { 19 | if (string.IsNullOrEmpty(scalar?.Value)) 20 | { 21 | return null; 22 | } 23 | 24 | return new IntstrIntOrString(scalar?.Value); 25 | } 26 | finally 27 | { 28 | parser?.MoveNext(); 29 | } 30 | } 31 | 32 | throw new InvalidOperationException(parser?.Current?.ToString()); 33 | } 34 | 35 | public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer) 36 | { 37 | var obj = (IntstrIntOrString)value; 38 | emitter?.Emit(new YamlDotNet.Core.Events.Scalar(obj?.Value)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/IntstrIntOrString.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | [JsonConverter(typeof(IntOrStringJsonConverter))] 4 | public partial class IntstrIntOrString 5 | { 6 | public static implicit operator IntstrIntOrString(int v) 7 | { 8 | return new IntstrIntOrString(Convert.ToString(v)); 9 | } 10 | 11 | public static implicit operator IntstrIntOrString(long v) 12 | { 13 | return new IntstrIntOrString(Convert.ToString(v)); 14 | } 15 | 16 | public static implicit operator string(IntstrIntOrString v) 17 | { 18 | return v?.Value; 19 | } 20 | 21 | public static implicit operator IntstrIntOrString(string v) 22 | { 23 | return new IntstrIntOrString(v); 24 | } 25 | 26 | protected bool Equals(IntstrIntOrString other) 27 | { 28 | return string.Equals(Value, other?.Value); 29 | } 30 | 31 | public override bool Equals(object obj) 32 | { 33 | if (ReferenceEquals(null, obj)) 34 | { 35 | return false; 36 | } 37 | 38 | if (ReferenceEquals(this, obj)) 39 | { 40 | return true; 41 | } 42 | 43 | if (obj.GetType() != GetType()) 44 | { 45 | return false; 46 | } 47 | 48 | return Equals((IntstrIntOrString)obj); 49 | } 50 | 51 | public override int GetHashCode() 52 | { 53 | return Value != null ? Value.GetHashCode() : 0; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/KubernetesEntityAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | /// 4 | /// Describes object type in Kubernetes 5 | /// 6 | [AttributeUsage(AttributeTargets.Class)] 7 | public sealed class KubernetesEntityAttribute : Attribute 8 | { 9 | /// 10 | /// The Kubernetes named schema this object is based on. 11 | /// 12 | public string Kind { get; set; } 13 | 14 | /// 15 | /// The Group this Kubernetes type belongs to. 16 | /// 17 | public string Group { get; set; } 18 | 19 | /// 20 | /// The API Version this Kubernetes type belongs to. 21 | /// 22 | public string ApiVersion { get; set; } 23 | 24 | /// 25 | /// The plural name of the entity. 26 | /// 27 | public string PluralName { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/ModelVersionConverter.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models; 2 | 3 | public static class ModelVersionConverter 4 | { 5 | public interface IModelVersionConverter 6 | { 7 | TTo Convert(TFrom from); 8 | } 9 | 10 | public static IModelVersionConverter Converter { get; set; } 11 | 12 | internal static TTo Convert(TFrom from) 13 | { 14 | if (Converter == null) 15 | { 16 | throw new InvalidOperationException("Converter is not set"); 17 | } 18 | 19 | return Converter.Convert(from); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/NodeMetrics.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | /// 4 | /// Describes the resource usage metrics of a node pull from metrics server API. 5 | /// 6 | public class NodeMetrics : IMetadata 7 | { 8 | /// 9 | /// The kubernetes standard object's metadata. 10 | /// 11 | [JsonPropertyName("metadata")] 12 | public V1ObjectMeta Metadata { get; set; } 13 | 14 | /// 15 | /// The timestamp when metrics were collected. 16 | /// 17 | [JsonPropertyName("timestamp")] 18 | public DateTime? Timestamp { get; set; } 19 | 20 | /// 21 | /// The interval from which metrics were collected. 22 | /// 23 | [JsonPropertyName("window")] 24 | public string Window { get; set; } 25 | 26 | /// 27 | /// The resource usage. 28 | /// 29 | [JsonPropertyName("usage")] 30 | public IDictionary Usage { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/NodeMetricsList.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | public class NodeMetricsList : IMetadata 4 | { 5 | /// 6 | /// Defines the versioned schema of this representation of an object. 7 | /// 8 | [JsonPropertyName("apiVersion")] 9 | public string ApiVersion { get; set; } 10 | 11 | /// 12 | /// Defines the REST resource this object represents. 13 | /// 14 | [JsonPropertyName("kind")] 15 | public string Kind { get; set; } 16 | 17 | /// 18 | /// The kubernetes standard object's metadata. 19 | /// 20 | [JsonPropertyName("metadata")] 21 | public V1ObjectMeta Metadata { get; set; } 22 | 23 | /// 24 | /// The list of node metrics. 25 | /// 26 | [JsonPropertyName("items")] 27 | public IEnumerable Items { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/PodMetrics.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | /// 4 | /// Describes the resource usage metrics of a pod pull from metrics server API. 5 | /// 6 | public class PodMetrics : IMetadata 7 | { 8 | /// 9 | /// The kubernetes standard object's metadata. 10 | /// 11 | [JsonPropertyName("metadata")] 12 | public V1ObjectMeta Metadata { get; set; } 13 | 14 | /// 15 | /// The timestamp when metrics were collected. 16 | /// 17 | [JsonPropertyName("timestamp")] 18 | public DateTime? Timestamp { get; set; } 19 | 20 | /// 21 | /// The interval from which metrics were collected. 22 | /// 23 | [JsonPropertyName("window")] 24 | public string Window { get; set; } 25 | 26 | /// 27 | /// The list of containers metrics. 28 | /// 29 | [JsonPropertyName("containers")] 30 | public List Containers { get; set; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/PodMetricsList.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | public class PodMetricsList : IMetadata 4 | { 5 | /// 6 | /// Defines the versioned schema of this representation of an object. 7 | /// 8 | [JsonPropertyName("apiVersion")] 9 | public string ApiVersion { get; set; } 10 | 11 | /// 12 | /// Defines the REST resource this object represents. 13 | /// 14 | [JsonPropertyName("kind")] 15 | public string Kind { get; set; } 16 | 17 | /// 18 | /// The kubernetes standard object's metadata. 19 | /// 20 | [JsonPropertyName("metadata")] 21 | public V1ObjectMeta Metadata { get; set; } 22 | 23 | /// 24 | /// The list of pod metrics. 25 | /// 26 | [JsonPropertyName("items")] 27 | public IEnumerable Items { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/ResourceQuantityJsonConverter.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | internal sealed class ResourceQuantityJsonConverter : JsonConverter 4 | { 5 | // https://github.com/kubernetes/apimachinery/blob/4b14f804a0babdcc58e695d72f77ad29f536511e/pkg/api/resource/quantity.go#L683 6 | public override ResourceQuantity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 7 | { 8 | switch (reader.TokenType) 9 | { 10 | case JsonTokenType.Null: 11 | return new ResourceQuantity(null); 12 | case JsonTokenType.Number: 13 | if (reader.TryGetDouble(out var val)) 14 | { 15 | return new ResourceQuantity(Convert.ToString(val)); 16 | } 17 | 18 | return reader.GetDecimal(); 19 | default: 20 | return new ResourceQuantity(reader.GetString()); 21 | } 22 | } 23 | 24 | public override void Write(Utf8JsonWriter writer, ResourceQuantity value, JsonSerializerOptions options) 25 | { 26 | if (writer == null) 27 | { 28 | throw new ArgumentNullException(nameof(writer)); 29 | } 30 | 31 | writer.WriteStringValue(value?.ToString()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/ResourceQuantityYamlConverter.cs: -------------------------------------------------------------------------------- 1 | using YamlDotNet.Core; 2 | using YamlDotNet.Serialization; 3 | 4 | namespace k8s.Models 5 | { 6 | public class ResourceQuantityYamlConverter : IYamlTypeConverter 7 | { 8 | public bool Accepts(Type type) 9 | { 10 | return type == typeof(ResourceQuantity); 11 | } 12 | 13 | public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) 14 | { 15 | if (parser?.Current is YamlDotNet.Core.Events.Scalar scalar) 16 | { 17 | try 18 | { 19 | if (string.IsNullOrEmpty(scalar?.Value)) 20 | { 21 | return null; 22 | } 23 | 24 | return new ResourceQuantity(scalar?.Value); 25 | } 26 | finally 27 | { 28 | parser?.MoveNext(); 29 | } 30 | } 31 | 32 | throw new InvalidOperationException(parser?.Current?.ToString()); 33 | } 34 | 35 | public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer) 36 | { 37 | var obj = (ResourceQuantity)value; 38 | emitter?.Emit(new YamlDotNet.Core.Events.Scalar(obj?.ToString())); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/V1Patch.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | [JsonConverter(typeof(V1PatchJsonConverter))] 4 | public partial class V1Patch 5 | { 6 | public enum PatchType 7 | { 8 | /// 9 | /// not set, this is not allowed 10 | /// 11 | Unknown, 12 | 13 | /// 14 | /// content type application/json-patch+json 15 | /// 16 | JsonPatch, 17 | 18 | /// 19 | /// content type application/merge-patch+json 20 | /// 21 | MergePatch, 22 | 23 | /// 24 | /// content type application/strategic-merge-patch+json 25 | /// 26 | StrategicMergePatch, 27 | 28 | /// 29 | /// content type application/apply-patch+yaml 30 | /// 31 | ApplyPatch, 32 | } 33 | 34 | public PatchType Type { get; private set; } 35 | 36 | public V1Patch(object body, PatchType type) 37 | { 38 | Content = body; 39 | Type = type; 40 | CustomInit(); 41 | } 42 | 43 | partial void CustomInit() 44 | { 45 | if (Content == null) 46 | { 47 | throw new ArgumentNullException(nameof(Content), "object must be set"); 48 | } 49 | 50 | if (Type == PatchType.Unknown) 51 | { 52 | throw new ArgumentException("patch type must be set", nameof(Type)); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/V1PatchJsonConverter.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | internal sealed class V1PatchJsonConverter : JsonConverter 4 | { 5 | public override V1Patch Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 6 | { 7 | throw new NotImplementedException(); 8 | } 9 | 10 | public override void Write(Utf8JsonWriter writer, V1Patch value, JsonSerializerOptions options) 11 | { 12 | if (writer == null) 13 | { 14 | throw new ArgumentNullException(nameof(writer)); 15 | } 16 | 17 | var content = value?.Content; 18 | if (content is string s) 19 | { 20 | writer.WriteRawValue(s); 21 | return; 22 | } 23 | 24 | JsonSerializer.Serialize(writer, content, options); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/V1PodTemplateSpec.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | /// 4 | /// Partial implementation of the IMetadata interface 5 | /// to open this class up to ModelExtensions methods 6 | /// 7 | public partial class V1PodTemplateSpec : IMetadata 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/V1Status.ObjectView.cs: -------------------------------------------------------------------------------- 1 | namespace k8s.Models 2 | { 3 | public partial class V1Status 4 | { 5 | internal sealed class V1StatusObjectViewConverter : JsonConverter 6 | { 7 | public override V1Status Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 8 | { 9 | var obj = JsonElement.ParseValue(ref reader); 10 | 11 | try 12 | { 13 | return obj.Deserialize(); 14 | } 15 | catch (JsonException) 16 | { 17 | // should be an object 18 | } 19 | 20 | return new V1Status { _original = obj, HasObject = true }; 21 | } 22 | 23 | public override void Write(Utf8JsonWriter writer, V1Status value, JsonSerializerOptions options) 24 | { 25 | throw new NotImplementedException(); // will not send v1status to server 26 | } 27 | } 28 | 29 | private JsonElement _original; 30 | 31 | public bool HasObject { get; private set; } 32 | 33 | public T ObjectView() 34 | { 35 | return _original.Deserialize(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/KubernetesClient/Models/V1Status.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace k8s.Models 4 | { 5 | public partial class V1Status 6 | { 7 | /// Converts a object into a short description of the status. 8 | /// string description of the status 9 | public override string ToString() 10 | { 11 | var reason = Reason; 12 | if (string.IsNullOrEmpty(reason) && Code.GetValueOrDefault() != 0) 13 | { 14 | reason = ((HttpStatusCode)Code.Value).ToString(); 15 | } 16 | 17 | return string.IsNullOrEmpty(Message) ? string.IsNullOrEmpty(reason) ? Status : reason : 18 | string.IsNullOrEmpty(reason) ? Message : $"{reason} - {Message}"; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/KubernetesClient/StreamType.cs: -------------------------------------------------------------------------------- 1 | namespace k8s 2 | { 3 | /// 4 | /// When creating a object, specify to properly handle 5 | /// the underlying communication. 6 | /// 7 | public enum StreamType 8 | { 9 | /// 10 | /// This object is used to stream a remote command or attach to a remote 11 | /// container. 12 | /// 13 | RemoteCommand, 14 | 15 | /// 16 | /// This object is used in port forwarding. 17 | /// 18 | PortForward, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/KubernetesClient/Utilities.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace k8s 4 | { 5 | internal static class Utilities 6 | { 7 | internal static void AddQueryParameter(StringBuilder sb, string key, string value) 8 | { 9 | if (sb == null) 10 | { 11 | throw new ArgumentNullException(nameof(sb)); 12 | } 13 | 14 | if (string.IsNullOrEmpty(key)) 15 | { 16 | throw new ArgumentNullException(nameof(key)); 17 | } 18 | 19 | sb.Append(sb.Length != 0 ? '&' : '?').Append(Uri.EscapeDataString(key)).Append('='); 20 | if (!string.IsNullOrEmpty(value)) 21 | { 22 | sb.Append(Uri.EscapeDataString(value)); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/EmbedResource.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Reflection; 3 | 4 | namespace LibKubernetesGenerator; 5 | 6 | internal static class EmbedResource 7 | { 8 | public static string GetResource(string name) 9 | { 10 | var assembly = Assembly.GetExecutingAssembly(); 11 | 12 | var resourceName = assembly.GetName().Name + "." + name; 13 | 14 | using var stream = assembly.GetManifestResourceStream(resourceName); 15 | using var reader = new StreamReader(stream ?? throw new FileNotFoundException(resourceName)); 16 | return reader.ReadToEnd(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/GeneratorExecutionContextExt.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.Text; 3 | using Scriban; 4 | using Scriban.Runtime; 5 | using System.Text; 6 | 7 | namespace LibKubernetesGenerator 8 | { 9 | internal static class GeneratorExecutionContextExt 10 | { 11 | public static void RenderToContext(this IncrementalGeneratorPostInitializationContext context, string templatefile, ScriptObject sc, string generatedfile) 12 | { 13 | var tc = new TemplateContext(); 14 | tc.PushGlobal(sc); 15 | context.RenderToContext(templatefile, tc, generatedfile); 16 | } 17 | 18 | public static void RenderToContext(this IncrementalGeneratorPostInitializationContext context, string templatefile, TemplateContext tc, string generatedfile) 19 | { 20 | var template = Template.Parse(EmbedResource.GetResource(templatefile)); 21 | var generated = template.Render(tc); 22 | context.AddSource(generatedfile, SourceText.From(generated, Encoding.UTF8)); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/IScriptObjectHelper.cs: -------------------------------------------------------------------------------- 1 | using Scriban.Runtime; 2 | 3 | namespace LibKubernetesGenerator; 4 | 5 | internal interface IScriptObjectHelper 6 | { 7 | void RegisterHelper(ScriptObject scriptObject); 8 | } 9 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/ModelExtGenerator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using NSwag; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace LibKubernetesGenerator 7 | { 8 | internal class ModelExtGenerator 9 | { 10 | private readonly ClassNameHelper classNameHelper; 11 | private readonly ScriptObjectFactory scriptObjectFactory; 12 | 13 | public ModelExtGenerator(ClassNameHelper classNameHelper, ScriptObjectFactory scriptObjectFactory) 14 | { 15 | this.classNameHelper = classNameHelper; 16 | this.scriptObjectFactory = scriptObjectFactory; 17 | } 18 | 19 | public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializationContext context) 20 | { 21 | // Generate the interface declarations 22 | var skippedTypes = new HashSet { "V1WatchEvent" }; 23 | 24 | var definitions = swagger.Definitions.Values 25 | .Where( 26 | d => d.ExtensionData != null 27 | && d.ExtensionData.ContainsKey("x-kubernetes-group-version-kind") 28 | && !skippedTypes.Contains(classNameHelper.GetClassName(d))); 29 | 30 | var sc = scriptObjectFactory.CreateScriptObject(); 31 | sc.SetValue("definitions", definitions, true); 32 | 33 | context.RenderToContext("ModelExtensions.cs.template", sc, "ModelExtensions.g.cs"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/ModelGenerator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using NSwag; 3 | 4 | namespace LibKubernetesGenerator 5 | { 6 | internal class ModelGenerator 7 | { 8 | private readonly ClassNameHelper classNameHelper; 9 | private readonly ScriptObjectFactory scriptObjectFactory; 10 | 11 | public ModelGenerator(ClassNameHelper classNameHelper, ScriptObjectFactory scriptObjectFactory) 12 | { 13 | this.classNameHelper = classNameHelper; 14 | this.scriptObjectFactory = scriptObjectFactory; 15 | } 16 | 17 | public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializationContext context) 18 | { 19 | var sc = scriptObjectFactory.CreateScriptObject(); 20 | 21 | 22 | foreach (var kv in swagger.Definitions) 23 | { 24 | var def = kv.Value; 25 | var clz = classNameHelper.GetClassNameForSchemaDefinition(def); 26 | 27 | sc.SetValue("clz", clz, true); 28 | sc.SetValue("def", def, true); 29 | sc.SetValue("properties", def.Properties.Values, true); 30 | 31 | context.RenderToContext("Model.cs.template", sc, $"Models_{clz}.g.cs"); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/ScriptObjectFactory.cs: -------------------------------------------------------------------------------- 1 | using Scriban.Runtime; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace LibKubernetesGenerator; 6 | 7 | internal class ScriptObjectFactory 8 | { 9 | private readonly List scriptObjectHelpers; 10 | 11 | public ScriptObjectFactory(IEnumerable scriptObjectHelpers) 12 | { 13 | this.scriptObjectHelpers = scriptObjectHelpers.ToList(); 14 | } 15 | 16 | public ScriptObject CreateScriptObject() 17 | { 18 | var scriptObject = new ScriptObject(); 19 | foreach (var helper in scriptObjectHelpers) 20 | { 21 | helper.RegisterHelper(scriptObject); 22 | } 23 | 24 | return scriptObject; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/SourceGenerationContextGenerator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using NSwag; 3 | 4 | namespace LibKubernetesGenerator 5 | { 6 | internal class SourceGenerationContextGenerator 7 | { 8 | private readonly ScriptObjectFactory scriptObjectFactory; 9 | 10 | public SourceGenerationContextGenerator(ScriptObjectFactory scriptObjectFactory) 11 | { 12 | this.scriptObjectFactory = scriptObjectFactory; 13 | } 14 | 15 | public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializationContext context) 16 | { 17 | var definitions = swagger.Definitions.Values; 18 | var sc = scriptObjectFactory.CreateScriptObject(); 19 | sc.SetValue("definitions", definitions, true); 20 | 21 | context.RenderToContext("SourceGenerationContext.cs.template", sc, "SourceGenerationContext.g.cs"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/UtilHelper.cs: -------------------------------------------------------------------------------- 1 | using NSwag; 2 | using Scriban.Runtime; 3 | 4 | namespace LibKubernetesGenerator 5 | { 6 | internal class UtilHelper : IScriptObjectHelper 7 | { 8 | public void RegisterHelper(ScriptObject scriptObject) 9 | { 10 | scriptObject.Import(nameof(IfKindIs), IfKindIs); 11 | } 12 | 13 | public static bool IfKindIs(OpenApiParameter parameter, string kind) 14 | { 15 | if (parameter != null) 16 | { 17 | if (kind == "query" && parameter.Kind == OpenApiParameterKind.Query) 18 | { 19 | return true; 20 | } 21 | else if (kind == "path" && parameter.Kind == OpenApiParameterKind.Path) 22 | { 23 | return true; 24 | } 25 | } 26 | 27 | return false; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/VersionGenerator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using NSwag; 3 | 4 | namespace LibKubernetesGenerator; 5 | 6 | internal class VersionGenerator 7 | { 8 | public void Generate(OpenApiDocument swagger, IncrementalGeneratorPostInitializationContext context) 9 | { 10 | context.AddSource("k8sver.cs", $"// \n" + "internal static partial class ThisAssembly { internal const string KubernetesSwaggerVersion = \"" + swagger.Info.Version + "\";}"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/generators/LibKubernetesGenerator/LibKubernetesGenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(DefineConstants);GENERATE_BASIC; 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/templates/AbstractKubernetes.cs.template: -------------------------------------------------------------------------------- 1 | // 2 | // Code generated by https://github.com/kubernetes-client/csharp/tree/master/src/LibKubernetesGenerator 3 | // Changes may cause incorrect behavior and will be lost if the code is 4 | // regenerated. 5 | // 6 | 7 | namespace k8s; 8 | 9 | /// 10 | /// 11 | public abstract partial class AbstractKubernetes 12 | { 13 | {{for group in groups}} 14 | public I{{group}}Operations {{group}} => this; 15 | {{end}} 16 | } 17 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/templates/ClientSet.cs.template: -------------------------------------------------------------------------------- 1 | // 2 | // Code generated by https://github.com/kubernetes-client/csharp/tree/master/src/LibKubernetesGenerator 3 | // Changes may cause incorrect behavior and will be lost if the code is 4 | // regenerated. 5 | // 6 | 7 | namespace k8s.ClientSets; 8 | 9 | /// 10 | /// 11 | public partial class ClientSet 12 | { 13 | {{for group in groups}} 14 | public {{group}}GroupClient {{group}} => new {{group}}GroupClient(_kubernetes); 15 | {{end}} 16 | } 17 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/templates/GroupClient.cs.template: -------------------------------------------------------------------------------- 1 | // 2 | // Code generated by https://github.com/kubernetes-client/csharp/tree/master/src/LibKubernetesGenerator 3 | // Changes may cause incorrect behavior and will be lost if the code is 4 | // regenerated. 5 | // 6 | 7 | namespace k8s.ClientSets; 8 | 9 | 10 | /// 11 | /// 12 | public partial class {{name}}GroupClient 13 | { 14 | private readonly Kubernetes _kubernetes; 15 | 16 | {{for client in clients}} 17 | public {{client}}Client {{client}} => new {{client}}Client(_kubernetes); 18 | {{end}} 19 | 20 | public {{name}}GroupClient(Kubernetes kubernetes) 21 | { 22 | _kubernetes = kubernetes; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/templates/IBasicKubernetes.cs.template: -------------------------------------------------------------------------------- 1 | // 2 | // Code generated by https://github.com/kubernetes-client/csharp/tree/master/src/LibKubernetesGenerator 3 | // Changes may cause incorrect behavior and will be lost if the code is 4 | // regenerated. 5 | // 6 | 7 | namespace k8s; 8 | 9 | /// 10 | /// 11 | public partial interface IBasicKubernetes 12 | { 13 | {{for group in groups}} 14 | I{{group}}Operations {{group}} { get; } 15 | {{end}} 16 | } -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/templates/ModelExtensions.cs.template: -------------------------------------------------------------------------------- 1 | // 2 | // Code generated by https://github.com/kubernetes-client/csharp/tree/master/src/LibKubernetesGenerator 3 | // Changes may cause incorrect behavior and will be lost if the code is regenerated. 4 | // 5 | namespace k8s.Models 6 | { 7 | {{ for definition in definitions }} 8 | [KubernetesEntity(Group=KubeGroup, Kind=KubeKind, ApiVersion=KubeApiVersion, PluralName=KubePluralName)] 9 | public partial class {{ GetClassName definition }} : {{ GetInterfaceName definition }} 10 | { 11 | public const string KubeApiVersion = "{{ GetApiVersion definition }}"; 12 | public const string KubeKind = "{{ GetKind definition }}"; 13 | public const string KubeGroup = "{{ GetGroup definition }}"; 14 | public const string KubePluralName = "{{ GetPlural definition }}"; 15 | } 16 | {{ end }} 17 | } 18 | -------------------------------------------------------------------------------- /src/LibKubernetesGenerator/templates/SourceGenerationContext.cs.template: -------------------------------------------------------------------------------- 1 | // 2 | // Code generated by https://github.com/kubernetes-client/csharp/tree/master/src/LibKubernetesGenerator 3 | // Changes may cause incorrect behavior and will be lost if the code is regenerated. 4 | // 5 | #if NET8_0_OR_GREATER 6 | namespace k8s 7 | { 8 | {{ for definition in definitions }} 9 | [JsonSerializable(typeof({{ GetClassName definition }}))] 10 | {{ end }} 11 | internal partial class SourceGenerationContext : JsonSerializerContext 12 | { 13 | } 14 | } 15 | #endif -------------------------------------------------------------------------------- /src/nuget.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": 3 | "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 4 | "settings": { 5 | "orderingRules": { 6 | "systemUsingDirectivesFirst": false, 7 | "usingDirectivesPlacement": "outsideNamespace" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/E2E.Aot.Tests/E2E.Aot.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | k8s.E2E 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /tests/E2E.Tests/E2E.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | k8s.E2E 5 | net8.0;net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /tests/E2E.Tests/KubectlTests.cs: -------------------------------------------------------------------------------- 1 | using k8s.kubectl.beta; 2 | using System.Linq; 3 | using Xunit; 4 | 5 | namespace k8s.E2E; 6 | 7 | [Collection(nameof(Onebyone))] 8 | public class KubectlTests 9 | { 10 | [MinikubeFact] 11 | public void CordonTest() 12 | { 13 | var client = MinikubeTests.CreateClient(); 14 | 15 | var node = client.CoreV1.ListNode().Items.First(); 16 | var nodeName = node.Metadata.Name; 17 | 18 | var kubectl = new Kubectl(client); 19 | 20 | // cordon 21 | kubectl.Cordon(nodeName); 22 | 23 | // check node status 24 | var cordonNode = client.CoreV1.ReadNode(nodeName); 25 | Assert.True(cordonNode.Spec.Unschedulable); 26 | 27 | // uncordon 28 | kubectl.Uncordon(nodeName); 29 | cordonNode = client.CoreV1.ReadNode(nodeName); 30 | Assert.True(cordonNode.Spec.Unschedulable == null || cordonNode.Spec.Unschedulable == false); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/E2E.Tests/MinikubeFactAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace k8s.E2E 5 | { 6 | public sealed class MinikubeFactAttribute : FactAttribute 7 | { 8 | private static readonly bool HasEnv = !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("K8S_E2E_MINIKUBE")); 9 | 10 | public override string Skip => !HasEnv ? "K8S_E2_MINIKUBE not set" : null; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/E2E.Tests/Onebyone.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace k8s.E2E; 4 | 5 | [CollectionDefinition(nameof(Onebyone), DisableParallelization = true)] 6 | public class Onebyone 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /tests/Kubectl.Tests/Kubectl.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0;net9.0 5 | enable 6 | enable 7 | false 8 | k8s.kubectl.Tests 9 | 10 | 11 | 12 | 13 | 14 | 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /tests/Kubectl.Tests/KubectlTests.Version.cs: -------------------------------------------------------------------------------- 1 | using k8s.E2E; 2 | using k8s.kubectl.beta; 3 | using System.Text.Json; 4 | using Xunit; 5 | 6 | namespace k8s.kubectl.Tests; 7 | 8 | public partial class KubectlTests 9 | { 10 | [MinikubeFact] 11 | public void Version() 12 | { 13 | using var kubernetes = MinikubeTests.CreateClient(); 14 | var client = new Kubectl(kubernetes); 15 | var version = client.Version(); 16 | var serverobj = version.ServerVersion; 17 | 18 | var output = RunKubectl("version"); 19 | 20 | var serverstr = output.Split('\n').Skip(1).First().Trim(); 21 | 22 | Assert.Equal(serverstr, $"Server Version: version.Info{{Major:\"{serverobj.Major}\", Minor:\"{serverobj.Minor}\", GitVersion:\"{serverobj.GitVersion}\", GitCommit:\"{serverobj.GitCommit}\", GitTreeState:\"{serverobj.GitTreeState}\", BuildDate:\"{serverobj.BuildDate}\", GoVersion:\"{serverobj.GoVersion}\", Compiler:\"{serverobj.Compiler}\", Platform:\"{serverobj.Platform}\"}}"); 23 | 24 | dynamic? swagger = JsonSerializer.Deserialize(File.OpenRead("swagger.json"), new 25 | { 26 | info = new 27 | { 28 | version = "", 29 | }, 30 | }.GetType()); 31 | 32 | Assert.Equal(swagger?.info.version, version.ClientSwaggerVersion); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Kubectl.Tests/KubectlTests.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace k8s.kubectl.Tests; 4 | 5 | public partial class KubectlTests 6 | { 7 | private string RunKubectl(string args) 8 | { 9 | var p = new Process 10 | { 11 | StartInfo = new ProcessStartInfo 12 | { 13 | FileName = "kubectl", 14 | Arguments = args, 15 | UseShellExecute = false, 16 | RedirectStandardOutput = true, 17 | RedirectStandardError = true, 18 | CreateNoWindow = true, 19 | }, 20 | }; 21 | 22 | p.Start(); 23 | 24 | try 25 | { 26 | if (!p.WaitForExit((int)TimeSpan.FromSeconds(30).TotalMilliseconds)) 27 | { 28 | throw new Exception("kubectl timed out"); 29 | } 30 | 31 | if (p.ExitCode != 0) 32 | { 33 | throw new Exception(p.StandardError.ReadToEnd()); 34 | } 35 | 36 | return p.StandardOutput.ReadToEnd(); 37 | } 38 | finally 39 | { 40 | p.Kill(true); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Classic.Tests/KubernetesClient.Classic.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | k8s.Tests 5 | net8.0;net9.0 6 | net8.0;net9.0;net48 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | [assembly: CollectionBehavior(DisableTestParallelization = true)] 4 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/ExternalExecutionTests.cs: -------------------------------------------------------------------------------- 1 | using k8s.KubeConfigModels; 2 | using System.Collections.Generic; 3 | using System.Text.Json; 4 | using Xunit; 5 | 6 | namespace k8s.Tests 7 | { 8 | public class ExternalExecutionTests 9 | { 10 | [Fact] 11 | public void CreateRunnableExternalProcess() 12 | { 13 | var actual = KubernetesClientConfiguration.CreateRunnableExternalProcess(new ExternalExecution 14 | { 15 | ApiVersion = "testingversion", 16 | Command = "command", 17 | Arguments = new List { "arg1", "arg2" }, 18 | EnvironmentVariables = new List> 19 | { new Dictionary { { "name", "testkey" }, { "value", "testvalue" } } }, 20 | }); 21 | 22 | var actualExecInfo = JsonSerializer.Deserialize>(actual.StartInfo.EnvironmentVariables["KUBERNETES_EXEC_INFO"]); 23 | Assert.Equal("testingversion", actualExecInfo["apiVersion"].ToString()); 24 | Assert.Equal("ExecCredentials", actualExecInfo["kind"].ToString()); 25 | 26 | Assert.Equal("command", actual.StartInfo.FileName); 27 | Assert.Equal("arg1 arg2", actual.StartInfo.Arguments); 28 | Assert.Equal("testvalue", actual.StartInfo.EnvironmentVariables["testkey"]); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/IntOrStringTests.cs: -------------------------------------------------------------------------------- 1 | using k8s.Models; 2 | using Xunit; 3 | 4 | namespace k8s.Tests 5 | { 6 | public class IntOrStringTests 7 | { 8 | [Fact] 9 | public void Serialize() 10 | { 11 | { 12 | var v = 123; 13 | IntstrIntOrString intorstr = v; 14 | 15 | Assert.Equal("123", KubernetesJson.Serialize(intorstr)); 16 | } 17 | 18 | { 19 | IntstrIntOrString intorstr = "12%"; 20 | Assert.Equal("\"12%\"", KubernetesJson.Serialize(intorstr)); 21 | } 22 | } 23 | 24 | [Fact] 25 | public void Deserialize() 26 | { 27 | { 28 | var v = KubernetesJson.Deserialize("1234"); 29 | Assert.Equal("1234", v.Value); 30 | } 31 | 32 | { 33 | var v = KubernetesJson.Deserialize("\"12%\""); 34 | Assert.Equal("12%", v.Value); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/ItemsEnumTests.cs: -------------------------------------------------------------------------------- 1 | using k8s.Models; 2 | using Xunit; 3 | 4 | namespace k8s.Tests; 5 | 6 | public class ItemsEnumTests 7 | { 8 | [Fact] 9 | public void EnsureIItemsEnumerable() 10 | { 11 | var pods = new V1PodList 12 | { 13 | Items = new[] { new V1Pod() }, 14 | }; 15 | 16 | // ensure no sytax err 17 | foreach (var pod in pods) 18 | { 19 | Assert.NotNull(pod); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/KubernetesClient.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | k8s.Tests 5 | net8.0;net9.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/Mock/MockWebSocketBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Net.WebSockets; 5 | using System.Security.Cryptography.X509Certificates; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace k8s.Tests.Mock 10 | { 11 | public class MockWebSocketBuilder : WebSocketBuilder 12 | { 13 | public Dictionary RequestHeaders { get; } 14 | = new Dictionary(); 15 | 16 | public Collection Certificates { get; } 17 | = new Collection(); 18 | 19 | public Uri Uri { get; private set; } 20 | 21 | public WebSocket PublicWebSocket => this.WebSocket; 22 | 23 | public override WebSocketBuilder AddClientCertificate(X509Certificate2 certificate) 24 | { 25 | this.Certificates.Add(certificate); 26 | return this; 27 | } 28 | 29 | public override Task BuildAndConnectAsync(Uri uri, CancellationToken cancellationToken) 30 | { 31 | this.Uri 32 | = uri; 33 | 34 | return Task.FromResult(this.PublicWebSocket); 35 | } 36 | 37 | public override WebSocketBuilder SetRequestHeader(string headerName, string headerValue) 38 | { 39 | this.RequestHeaders.Add(headerName, headerValue); 40 | return this; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/Mock/Server/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using System; 5 | 6 | namespace k8s.Tests.Mock.Server 7 | { 8 | /// 9 | /// Startup logic for the KubeClient WebSockets test server. 10 | /// 11 | public class Startup 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// Create a new . 16 | /// 17 | public Startup() 18 | { 19 | } 20 | 21 | /// 22 | /// Configure application services. 23 | /// 24 | /// 25 | /// The service collection to configure. 26 | /// 27 | public static void ConfigureServices(IServiceCollection services) 28 | { 29 | if (services == null) 30 | { 31 | throw new ArgumentNullException(nameof(services)); 32 | } 33 | 34 | services.AddLogging(logging => 35 | { 36 | logging.ClearProviders(); // Logger provider will be added by the calling test. 37 | }); 38 | services.AddMvc(opt => opt.EnableEndpointRouting = false); 39 | } 40 | 41 | /// 42 | /// Configure the application pipeline. 43 | /// 44 | /// 45 | /// The application pipeline builder. 46 | /// 47 | public static void Configure(IApplicationBuilder app) 48 | { 49 | app.UseWebSockets(new WebSocketOptions 50 | { 51 | KeepAliveInterval = TimeSpan.FromSeconds(5), 52 | }); 53 | app.UseMvc(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/OperatingSystemDependentFactAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using Xunit; 3 | 4 | namespace k8s.Tests 5 | { 6 | public class OperatingSystemDependentFactAttribute : FactAttribute 7 | { 8 | public OperatingSystems Include { get; set; } = OperatingSystems.Linux | OperatingSystems.Windows | OperatingSystems.OSX; 9 | public OperatingSystems Exclude { get; set; } 10 | 11 | public override string Skip 12 | { 13 | get => IsOS(Include) && !IsOS(Exclude) ? null : "Not compatible with current OS"; 14 | set { } 15 | } 16 | 17 | private bool IsOS(OperatingSystems operatingSystems) 18 | { 19 | if (operatingSystems.HasFlag(OperatingSystems.Linux) && RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 20 | { 21 | return true; 22 | } 23 | 24 | if (operatingSystems.HasFlag(OperatingSystems.Windows) && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 25 | { 26 | return true; 27 | } 28 | 29 | if (operatingSystems.HasFlag(OperatingSystems.OSX) && RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) 30 | { 31 | return true; 32 | } 33 | 34 | return false; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/OperatingSystems.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace k8s.Tests 4 | { 5 | [Flags] 6 | public enum OperatingSystems 7 | { 8 | /// Windows operating system. 9 | Windows = 1, 10 | 11 | /// Linux operating system. 12 | Linux = 2, 13 | 14 | /// OSX operating system. 15 | OSX = 4, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/TaskAssert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Xunit; 4 | 5 | namespace k8s.Tests 6 | { 7 | internal static class TaskAssert 8 | { 9 | public static void NotCompleted(Task task, string message = "Task should not be completed") 10 | { 11 | Assert.False(task.IsCompleted, message); 12 | } 13 | 14 | public static async Task Completed(Task task, TimeSpan timeout, string message = "Task timed out") 15 | { 16 | var timeoutTask = Task.Delay( 17 | TimeSpan.FromMilliseconds(1000)); 18 | 19 | var completedTask = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false); 20 | Assert.True(ReferenceEquals(task, completedTask), message); 21 | 22 | await completedTask.ConfigureAwait(false); 23 | } 24 | 25 | public static async Task Completed(Task task, TimeSpan timeout, string message = "Task timed out") 26 | { 27 | var timeoutTask = Task.Delay(TimeSpan.FromMilliseconds(1000)).ContinueWith(completedTimeoutTask => default(T)); 28 | 29 | // Value is never returned, but we need a task of the same result type in order to use Task.WhenAny. 30 | 31 | var completedTask = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false); 32 | Assert.True(ReferenceEquals(task, completedTask), message); 33 | 34 | return await completedTask.ConfigureAwait(false); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/TokenFileAuthTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | using k8s.Authentication; 3 | using System; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | 8 | namespace k8s.Tests 9 | { 10 | public class TokenFileAuthTests 11 | { 12 | [Fact] 13 | public async Task TestToken() 14 | { 15 | var auth = new TokenFileAuth("assets/token1"); 16 | var result = await auth.GetAuthenticationHeaderAsync(CancellationToken.None).ConfigureAwait(true); 17 | result.Scheme.Should().Be("Bearer"); 18 | result.Parameter.Should().Be("token1"); 19 | 20 | auth.TokenFile = "assets/token2"; 21 | result = await auth.GetAuthenticationHeaderAsync(CancellationToken.None).ConfigureAwait(true); 22 | result.Scheme.Should().Be("Bearer"); 23 | result.Parameter.Should().Be("token1"); 24 | 25 | auth.TokenExpiresAt = DateTime.UtcNow.AddSeconds(-1); 26 | result = await auth.GetAuthenticationHeaderAsync(CancellationToken.None).ConfigureAwait(true); 27 | result.Scheme.Should().Be("Bearer"); 28 | result.Parameter.Should().Be("token2"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/UtilityTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Xunit; 4 | 5 | namespace k8s.Tests 6 | { 7 | public class UtilityTests 8 | { 9 | [Fact] 10 | public void TestQueryStringUtilities() 11 | { 12 | var sb = new StringBuilder(); 13 | Assert.Throws(() => Utilities.AddQueryParameter(null, "key", "value")); 14 | Assert.Throws(() => Utilities.AddQueryParameter(sb, null, "value")); 15 | Assert.Throws(() => Utilities.AddQueryParameter(sb, "", "value")); 16 | 17 | Utilities.AddQueryParameter(sb, "key", "value"); 18 | Utilities.AddQueryParameter(sb, "key", "a=b"); 19 | Utilities.AddQueryParameter(sb, "+key", null); 20 | Utilities.AddQueryParameter(sb, "ekey", ""); 21 | Assert.Equal("?key=value&key=a%3Db&%2Bkey=&ekey=", sb.ToString()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/ca-bundle-intermediate.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDDTCCAfWgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UEAwwKa3Vi 3 | ZXJuZXRlczAeFw0xOTAzMDMxNzA4MDlaFw0yOTAyMjgxNzA4MDlaMBYxFDASBgNV 4 | BAMMC2V0Y2hhbmctdWI1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 5 | x1Tp7Da3NbjdHmYdYZ/GNpCRGvFFap7EG1pokhfILKSbPusqiO9wnKDE4Afdn/ZE 6 | CQV0Whwtox3jczBOIRy+P6FvlPyhApUpynVTwgCiuhTM+thgODgpe6GXmVlVJGvv 7 | AoLw7CMndB5sMs5HH+qA2U1q4VFI/csr3/yeKzWBik3dZVoh04sI9WTVL+bl/1X5 8 | 0dl5qrqkYiDx8ycAHyOnl8dhJW+RGl67HiliuUeSq6vwsfv9rh3TP9wHVF1PXFJp 9 | WfXy4WbLmuld5wxXnQVO2g51jqfqN9fD8FHIkae1IkO/PUTucloNlLiFsragQOTD 10 | RVSP+TV3gshATBs2MMVXMwIDAQABo2YwZDAdBgNVHQ4EFgQU/3w9AR2cnEepWH4E 11 | 8a1xLZAnjykwHwYDVR0jBBgwFoAULs/lzct8CGvVdIiq4t9T4idu5OwwEgYDVR0T 12 | AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEB 13 | AKw741V1wszIthHBV8dvCyQoyozBJuAo4IHbiiFmzuiQuyshMcX+Qs9a+g6OG5d1 14 | UbwFfUlqzmZQcbcR/Jc6wMz3wO6Hoy5pS3w/FR2UMGR39o95/7XCkTIOwCqau6Pw 15 | dpgvbnaiqPFPqD3ohdUuVRcXG3va5AmKTsUn7m+lR/93/qptt+SUVp6jwnbGcwoB 16 | s3u2XXx5s1M7tqqj3tAEOPCKlohS6mQ4X3wulgpZ1XpJ0WTvcvoPXEtA56k7vX3a 17 | 4E6x66LZCFA2ZR/5COv5D055AhrihKL8kbAutxhfA27SJ/MGowzmTT7kVQha3Su3 18 | aoOYZgcUww+SkRSGVrtgMgQ= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/ca-bundle-root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDEDCCAfigAwIBAgIJAJpb9irKg2JjMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV 3 | BAMMCmt1YmVybmV0ZXMwHhcNMTkwMzAzMDAyMTI3WhcNMzkwMjI2MDAyMTI3WjAV 4 | MRMwEQYDVQQDDAprdWJlcm5ldGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 5 | CgKCAQEAuoK+Na+LyKIipmftBw4Y+Z19g8yv6Y+dYt6KlBg24XHNA0v1cMwtOCDF 6 | Mlm4rsD7Jd5UO6ugdk3fxEvGGhmzWTXSBRUWcTbScAM49mALBFkCvNTPK2vVhk7P 7 | im2QQl8a5vjYz8HLKJTb/O+0q+Kktpd7XTaU2U7ZebiLVs5bvNbb3ZDtIjAARY9S 8 | alZ4hOzuVNaSX9MBRqTWq3HuKwDiVTT3dan/ABoU8NdedPfIbyY48wiQgjEYb64g 9 | 3geYpArLQeffo8fmhUEPRR/1WrfvYvvm8sV8jT+rqxITKJ5Vo5kpZUpomDOtGVMS 10 | gGAle6mcTrqlrsCFc4gFRRoHiH1ODQIDAQABo2MwYTAdBgNVHQ4EFgQULs/lzct8 11 | CGvVdIiq4t9T4idu5OwwHwYDVR0jBBgwFoAULs/lzct8CGvVdIiq4t9T4idu5Oww 12 | DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD 13 | ggEBAFMq5z4OoaIhqx/i/btpVLRnQDcpDwdUurE0iNPz3bgOI5QiIe95oUwXSFQL 14 | ciECvObfMmiVuz+p7ND5eNdxYR4hlq1W1PYcgRQgusXCC4Xd/XAGaLZXzH3SBrmp 15 | bs5sfokhXKNccsnQu5Ya3JRkALxxUJ+DcOn+vi9gmEAzi+nXbyqUjIhSD5nygClX 16 | 0aSKbvhUmXyaJpUH0i7dSxWP3LqCDjtru/5ejNtB097dNcyF8js3Yuk3hwqyegQx 17 | ELn4c/TKPL9L8vE7tJg/M78DPAvRCiuwl0HQcasBE2AX0wdpY0UeXsNDyzUf/2WF 18 | fHY4DnuBdeVdHtl1yPlXmQkMoQM= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/ca-data.txt: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURERENDQWZTZ0F3SUJBZ0lSQUo5ZCtLeThkTDJVSzRjdXplMmo2WnN3RFFZSktvWklodmNOQVFFTEJRQXcKTHpFdE1Dc0dBMVVFQXhNa1lXRTBZVFV3T0RZdE0yVm1aaTAwWWpCa0xUbGxORGt0WmpNeVpXWXpabUpqWWpNNApNQjRYRFRFM01ESXlOakExTURRek5Gb1hEVEl5TURJeU5UQTFNRFF6TkZvd0x6RXRNQ3NHQTFVRUF4TWtZV0UwCllUVXdPRFl0TTJWbVppMDBZakJrTFRsbE5Ea3Raak15WldZelptSmpZak00TUlJQklqQU5CZ2txaGtpRzl3MEIKQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBM2dkandhdHNsdCsvQVpqV3hmbkNQeGZqMzNHUUxlOU00VU42VmEwRQpKd0FYL2R3L1ZVa0dvVjlDc3NKRUZMdEdTUnM2K2h0RTEvOUN3ak1USDh2WExKcURHTE9KdFQ5dW9sR2c2Q2k1ClBKNDNKelVLWmJlYVE4Z3hhZndzQjdQU05vTTJOYzROVm9lZzBVTUw0bndGeEhXeTNYWHlFZ0QxTWxTUnVrb3oKTTNoRUVxUjJNVFdrNm9KK3VJNFF4WVZWMnZuWXdXaEJwUDlDR3RWUTlyUW9MVFowcmFpOCtDYURBMVltTWRhbQpRYUVPdURlSFRqU2FYM2dyR0FBVVFWNWl6MC9qVVBuK3lJNm1iV0trbzFzNytPY1dZR2F1aDFaMzFYSjJsc0RTCnU4a3F0d215UEcyUVl2aUQ4YjNOWFAyY0dRK2EwZlpRZnBrbTF0U3IxQnhhaXdJREFRQUJveU13SVRBT0JnTlYKSFE4QkFmOEVCQU1DQWdRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQQpuVzFXVXlLbVJ0TlNzU1VzVFBSUnhFRzhhek9kdjdYeUhRL0R5VWNqWm9rUEJVVHY4VjdvNG96RHgyVHV6UEdYCmZ2YlMvT2g0VDd6ZlYxdjJadmU3dTBxelNiRTl5OGpsaDNxYXJEcEd5ZmlTamwycmhIOFBmay9sZGR0VFpVL04KSkVtYW5ReGl6R20xV2pCSklRSE5LZENneVIwN3A1c0MwNnR3K25YUytla1MxMlBUTG45WjBuRDBKVDdQSzRXQgpQc3ZXeDVXN0w5dnJIdVN5SGRSTkt5eEEvbWI1WHdXMDBkZUpmaHZub0p3ZWRYNDVKZVRiME5MczUzaURqVEU1CnRpdU03Z1RVSjlCcGZTL0gvYSt2SmovVWQ2bHM0QndrWmpUNHNhOTA1bnNzdnRqamlwZ1N5a0QzVkxCQ3VueTkKd1NnbE1vSnZNWmg0bC9FVFJPeFE3Zz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 2 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC5zCCAc+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p 3 | a3ViZUNBMB4XDTE3MDcyNDA1NDExNloXDTI3MDcyMjA1NDExNlowFTETMBEGA1UE 4 | AxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMfj 5 | J9bJarUsN5Ynt/sbDFQQLp6BeHPXOcUdbNan1YbXdFGN8qLKkkQz0YY1hcVGrXdj 6 | 3vd2s8x9XlOyQPZ1SX4vJa5x/67BzFdxbCLg6jBYAisGvYu0hV4jvhHYOZH8sWUp 7 | 6n+gPm5c3J8gjqAmM0VwpvtG9HBIr1MWQ4HSTCBVoPvuG9TkOyxrB9RCha16hG7j 8 | B3m9XNEkRVl1xvW6wkeTO4n5cFSoDG0bfCnnjf0oz+pf0yJoSHbl/f2jI/rggMft 9 | 0R0LJfqdGlNCKCuN4g0jMmf26313oe+7i8uU4ut9iM1OBv6vD+xy115DGYG7EQIy 10 | lC1rd+gNlGQSxDafAb8CAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW 11 | MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 12 | DQEBCwUAA4IBAQAnXDZUdfC22zyFpZ+Rez3tyk9SqpOeiN1xGirZ5obDgvOS9vSR 13 | GLrsdN4UtXfGpKeMNQJV4e9YDz1ehLd1MK1BoxDVZHB0Sm2QxuyA4EyPfpHH9zaY 14 | qoRgDeUKBmCteLLcY3ukOzGf915j+lWQHv+tk52gvHfxvRyEuawSxSnowkGGFY9R 15 | 6AQ2cFm7G3SdygRWVXT1hk5hVQXvBY9DNU1YNvN0qWE6ss5RHJ/cxHFWtrdcr86K 16 | DqW9Ylr1l2iwkWpnXR4OMK3ZFjwX/qi11Z8eMDOi+0FxZ/6BkGQxe7X6D2GjCZ3r 17 | Lfbj0HBpynkd6lfLmIWgEzGYxrQjvczbAKBD 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/ca2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC3zCCAcegAwIBAgIQWNOfSGBRn4EUcsj7E1UN8zANBgkqhkiG9w0BAQsFADAZ 3 | MRcwFQYDVQQKEw5EYXZpZCBPcmJlbGlhbjAeFw0xODA2MDgxMjI2MDBaFw0yMTA1 4 | MjMxMjI2MDBaMBkxFzAVBgNVBAoTDkRhdmlkIE9yYmVsaWFuMIIBIjANBgkqhkiG 5 | 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnXGK1ZHqF4fhO3WOtlo5kqVYHHYTasNmzbQh 6 | MJ0IHiFrCVNi6apohleHi0IlzVFCQY5+yab2Lz7J2qcadRVWLlfhskMx4hbSD+eX 7 | H9MDcnV1k4AyFz+9I+dL4rb5DPcK9vNQF0KXtdpaq4qVs+IoRR4Ck00yvzLmOMTs 8 | YvFVjW6XgKPR+y89y8iykW2puiJ/y6DLKlP+2HDGGEI07C+4Tkxps6uRkPz6ySVb 9 | 6mhJ6P/+8WmuMc0Ur1kNgA0GEUTFYlRNuF0nNjBvncGBUwOWAUNbsYQgElaqXJKe 10 | XZ6M44+oBvRsCsnf7j3hfKti4u/Qy9nDejJ/15R6I6A5JdYOxwIDAQABoyMwITAO 11 | BgNVHQ8BAf8EBAMCAqwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC 12 | AQEAU2Rp4T7iWomEsCC8nrQPXh/6AlVnfb/vhC7aCq+g6CF+LvksfM3Uj+JLQ5rM 13 | QNavSXowqe11vNb1Qu7LcQT5ff76XEoK0dKA8uMs60wUkHttfPzXM522rdv+i8EF 14 | QwVirN85W5i2q669MQ2BeJ37gQ6vQAOLvHXTuspDo1qrfT3zkeGiLEXRM4k4d6OT 15 | BnZNYvfdTTZX7OlvHfw5hdcRtoOTBmTAh+UKJvOUIQ2g/Mp2VBxNNC5zhJHTwEXj 16 | ssHyR24e9+GODLviep2H1uB+mHZQ5Yvzxxlkz8NTDx+mUmBSF1gGuDNdmKrCrP92 17 | bJZY0LcRrXX0aqPymVZrINDvtA== 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/client-certificate-data.txt: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURrVENDQW5tZ0F3SUJBZ0lVTzlVTkdpbHhmSHpMbVJXcWU2dVMyRVZ1NVhVd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RURBT0JnTlZCQWdUQjFKbFpHMXZibVF4Q3pBSkJnTlZCQWNUQWxkQgpNUk13RVFZRFZRUURFd3ByZFdKbGNtNWxkR1Z6TUNBWERURTRNVEl3T0RBNU5URXdNRm9ZRHpJeE1UZ3hNVEUwCk1EazFNVEF3V2pCQk1Rc3dDUVlEVlFRR0V3SlZVekVRTUE0R0ExVUVDQk1IVW1Wa2JXOXVaREVMTUFrR0ExVUUKQnhNQ1YwRXhFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQgpEd0F3Z2dFS0FvSUJBUUM4WkVRS296SE8zOExmRzRpcHFYWnRLTzNxSENjL1Z1WjUxWnZSeWJuTnpCYU5iMk9oClM0cU1nNDF6cFdzL3dMQnk4ZndPclpoOHpHb28wbHllQXVCSlBPWFc5SmswMmhOc1Y3ZHBqYXBZWFMrSXJvN04KcUxhWDB5amQxWWllSWFlb3NtV2xib2ZpcDVzS3dzVUI3bGREeXJpQklBYTEwNlhhTng5ZG82UEh1TDNibStldwpiaWRoRTlNUFRHY2V5WW9rZ3pNbGppanordk0yUnN5Z05ncmR4VDhROC9GRER2ZndTRmZUaEZlYXIzckQvRkJGCmVYb0Y5MHp6cG1aZlphTDlyZ2NjQ0pzQ2JSZlpiellVVERRVHo2dStaUVhUdGlrbVMvQ3d2d0hXa0w3bGhQNXYKQU0yVFpETEJhQXQwOU14dGlORFNWaFFTWVR2QWpKRmU4SzJoQWdNQkFBR2pmekI5TUE0R0ExVWREd0VCL3dRRQpBd0lGb0RBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFRWUlLd1lCQlFVSEF3SXdEQVlEVlIwVEFRSC9CQUl3CkFEQWRCZ05WSFE0RUZnUVVuQmo0T3Y3MnFlWWJ5YjVYSHJma1pkazd6VUF3SHdZRFZSMGpCQmd3Rm9BVUxwemQKRlplYkR6N0RmZUNkZkJqNmNkUWJmNk13RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQU1CL1RDaElEbTNkeDA4SApJeXlFS2dYUHh1d3A1cTB5QkFoT0pUS1JOVXNpayt6ZVUyUGpibnV0M3B1WnBENkZoTGFKQUZPbTdsMHhkNU1ZCkFZOVloSy9wa1U3Rmw1TFg0MitxQzRqK05JdGhBbFM5clNtNkRvNlN1b3JRcjdNajErY0syTjFkZHBtRWZya3kKZXZnMm02aFB5YTFlV0hNanVCd250bkJmV2EzWHBWMWVGZVBvd21zY3R6UmRJYUh3WDM3Yit3c2JmbkppczRvTgo2bHk0THBQb2xtYld3ZTRnaEtPWXNuL3lMT3FrUGJMZVpLeU5yaWJpSGhSQTM0NUVHUGJleXNmSlNIWWFqMnBaCmE0VmRTRFhnT2JlM3Vtdk9keXVEaGl5RFJ3TFozbVJLWlpIR0lzZC9ORzRncWo3a0gzV2N2Wm5mSkVHMXY2cG0KQTZFYTJiRT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/client.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDbjCCAlagAwIBAgIJAJD2bN6nz4ieMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV 3 | BAYTAlVTMQswCQYDVQQIDAJXQTENMAsGA1UEBwwEVGVzdDEhMB8GA1UECgwYSW50 4 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE3MDcyNzA0NTEyNloXDTE4MDcyNzA0 5 | NTEyNlowTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMQ0wCwYDVQQHDARUZXN0 6 | MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3 7 | DQEBAQUAA4IBDwAwggEKAoIBAQDG8khxm/q6ls7TTKlKtTJgiPh6Gh7w1dCJG04/ 8 | hyKuXMpx1WM0i943/M51k/X9XTuHgCOB/s191yBpNa6pHYgtuQGnzoMdHbRayggH 9 | 3i9x9jwEaf6RXFIuedRANzih+pVlDkXJftebE/YJwoOWes9SBPKqPOaGrC2A0Nqc 10 | s0iiZ/4oil3cXQYyzakwKQ9Mhb6M3Uw5OlfUCJXfAjsg5AIgrtYy//tXu3Cz+zIn 11 | tGvA3iWRIJfpCOziR3mMQc9GnFSeUHZCu/bFPCbc5yQ2Jy5Pm1y0coo/iPTEOw10 12 | RYXocr54lr854rtihHvKat5c/bkJQjpr8Mgy8qeVbAXzVtgRAgMBAAGjUzBRMB0G 13 | A1UdDgQWBBR9trLzkcB5I17ZGBeGhcjX8Ae5GTAfBgNVHSMEGDAWgBR9trLzkcB5 14 | I17ZGBeGhcjX8Ae5GTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB 15 | AQCXmgQLziUsWh0jDX/LhqwQxIM2YZDm8+K60my9gnWFv9B6OEvj3gilB69B0tuP 16 | YaJcpWhhzO+/pE8vxOBGQz731M7Er3TGpTrmBD/5bj9NJ71u0FxYjVA8lwbaQced 17 | l8bskTBAAiEZTzEEfdBHcHJXvpzLcnRZ1uNin3EYyyfl5dsZyHfyHUtMiMqzuEFP 18 | 8gusgANC3s0to41mZ6S3YJB/TcVKarFAYBg7FYQbIn2+qQg6B6itcZ8FzquffPDO 19 | 7od/iwL7Chh/AkrGQcRlHPZTzsDlpat2+0zHBYAVYVbuQMNaCD3IRh80Ufi+DpxL 20 | osKY7Mkcwj1Nmoz4JPoL0wYI 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDG8khxm/q6ls7T 3 | TKlKtTJgiPh6Gh7w1dCJG04/hyKuXMpx1WM0i943/M51k/X9XTuHgCOB/s191yBp 4 | Na6pHYgtuQGnzoMdHbRayggH3i9x9jwEaf6RXFIuedRANzih+pVlDkXJftebE/YJ 5 | woOWes9SBPKqPOaGrC2A0Nqcs0iiZ/4oil3cXQYyzakwKQ9Mhb6M3Uw5OlfUCJXf 6 | Ajsg5AIgrtYy//tXu3Cz+zIntGvA3iWRIJfpCOziR3mMQc9GnFSeUHZCu/bFPCbc 7 | 5yQ2Jy5Pm1y0coo/iPTEOw10RYXocr54lr854rtihHvKat5c/bkJQjpr8Mgy8qeV 8 | bAXzVtgRAgMBAAECggEASrptPcdyOa42CCaOnJJNVvd8JhkzsBEQYL/R94jiHQ6b 9 | uICH4A/9q5gZUQ7/4min2LDoJYc5VuB8uyg/8CQ4p7wLhCXNGB21RjkHJTVvKuZs 10 | Cthpl95OvEhk0q4rZqSCg1AGJLaxc/3eeDIJTXfZ8hwLrqhriwCXowBQbXXmfaHa 11 | YiOodBFs+B55si2NiO971wiz7jeFYYs/tEiT9wS6nvq0t2omSi7e8ryL103Lb1ge 12 | SAelzS4ZMCf/Xt+kYz+UeC51RlCshHt9sif0Jgst84EVqX5by2PzSUrQu6YPNLrn 13 | 3WulO6a7oqHYfF8wV4ARD89SNRyWcF/Xh+vjPg538QKBgQDx5W/x+F/Nt+f0tlDl 14 | ZeSoB/wWo2yQx0gK98R66M3qUtnoeWC+SSj15z1WPT+MfD+B2haytiFP1+uAveI/ 15 | hup1oJMddciTcLMfc13s7luXe+OLMCxCwJTrgaSZeD79dUKKzHv2yU4v01gJFlMq 16 | GnkAzUxolvb9sVzgFuCy7agHnQKBgQDSi8XxDoNhv9HAKHJDhQ1g3mmGIPPP4M72 17 | v8MxO5AXVCVcL3VFGj+7H6Z3CJuiE7diJVBSPMun/6q1xgMZNUe9EjIjCdmEKMOz 18 | Nm/5P6Dea1Gktd5gb6NB9GTpE3JqwxhxkM0VNv/k8rCp6+4Oz1d8uF+p6jPwNEC5 19 | Z9vlge/aBQKBgQCkv0nl9+5v8rAVF9Ky2hnIY1/Kn1VCqackaSk1OLd9vx3QWlKM 20 | ZtFx4SMCSEauzLSIINvSrX60nW80yJ59+8pVgJ6RsvV/jYNBiVZQFurkmikYVB/g 21 | +r6yQyKyr5XfE+zVEX3gT6xjoEJWNhFAHLWK2UgP97mSgSirKomw83G8dQKBgHWl 22 | fHlx7p/UG1QQRajM0+jo3nYAO7xQldTy2hLMgXtHnYihTBnMzQe2a8HfoXczJSlG 23 | SFdreTDqf20Ks/iF+QwA+trxSgW68X9WT8Mqdq1RslEi/ptMRiE4eppyL2DQmvv6 24 | OV49WUeJBIYuOtszqGMccvfy0grKZ9Ax5IGd1XQxAoGAW7DObS33nO9/arcEg+yK 25 | H0cOSP1h/8v4k4M4gorfuXfi6Xkegt5PaWUf7tJGDon5ArzZsCNRq5rdBMNtA4an 26 | NbMlanRzfBuBqHYo/X8OgqThhn8Uwg/oY778qHEH+WaJdSiNg5TboDPKUyEBNRKA 27 | suoE9MAZsAaIj4YP0RnMLk8= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/elliptic-client.key: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MIHcAgEBBEIAgsWy6kCIIGCuedLfU0zqElm7H9VwpzKWK3ITjtG8QPEJfw0vEqVL 3 | Ly4aVsZ8dH7lP6Ykz90lAxLPwMJTL7fht9qgBwYFK4EEACOhgYkDgYYABADJVVPm 4 | PwRHH96uMREAJMrznGswswqMerCY8wqGjAMDHCWE/bvbGROhRzZM5WNuI/C7d5oV 5 | YpagbVVgIi3L4Jr+hgDuAmK4AExQYcZWVcPqLe/kv7i5xxAT2MJwuto7QJeR7ffh 6 | YzbpOXqgQBrJW2Fdgh/mTAKHrtP/nDOsioRWzxl2zQ== 7 | -----END EC PRIVATE KEY----- 8 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/elliptic.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICBTCCAWYCFDt3JLija7g4s9TNSFI8p9topHs4MAoGCCqGSM49BAMCMEExCzAJ 3 | BgNVBAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTETMBEGA1UE 4 | CgwKS3ViZXJuZXRlczAeFw0yMTEwMjAwMDA2MDdaFw0yMTExMTkwMDA2MDdaMEEx 5 | CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTETMBEG 6 | A1UECgwKS3ViZXJuZXRlczCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAMlVU+Y/ 7 | BEcf3q4xEQAkyvOcazCzCox6sJjzCoaMAwMcJYT9u9sZE6FHNkzlY24j8Lt3mhVi 8 | lqBtVWAiLcvgmv6GAO4CYrgATFBhxlZVw+ot7+S/uLnHEBPYwnC62jtAl5Ht9+Fj 9 | Nuk5eqBAGslbYV2CH+ZMAoeu0/+cM6yKhFbPGXbNMAoGCCqGSM49BAMCA4GMADCB 10 | iAJCAL8VpSq+rs+h/BmNu/z0KCWsfQv7zOZOTOqYJ/5NzaBlEhejj8ktfvWTJ3SR 11 | jHIMWdK+SAJva1v1tzaTi5z7KiYuAkIApijJv9yr/Ex4okg6zB/LgsTio67fm4DG 12 | 9Yrw9KVtUbskcYjcpLVbT78cQjeDyDg1dYtHpdl7Z7p+jga/nPb/HKU= 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/gcloud-config-helper.json: -------------------------------------------------------------------------------- 1 | { 2 | "configuration": { 3 | "active_configuration": "default", 4 | "properties": { 5 | "compute": { 6 | "region": "us-east1", 7 | "zone": "us-east1-b" 8 | }, 9 | "core": { 10 | "account": "some@account.io", 11 | "disable_usage_reporting": "True", 12 | "project": "fe-astakhov" 13 | } 14 | } 15 | }, 16 | "credential": { 17 | "access_token": "ACCESS-TOKEN", 18 | "token_expiry": "2020-03-20T07:09:20Z" 19 | }, 20 | "sentinels": { 21 | "config_sentinel": "C:\\Users\\Andrew\\AppData\\Roaming\\gcloud\\config_sentinel" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.as-user-extra.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority: assets/ca.crt 5 | server: https://10.20.0.56:8443 6 | name: minikube 7 | contexts: 8 | - context: 9 | cluster: minikube 10 | user: minikube 11 | name: minikube 12 | current-context: minikube 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: minikube 17 | user: 18 | as-user-extra: {} 19 | client-certificate: assets/client.crt 20 | client-key: assets/client.key 21 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.cluster-extensions.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | extensions: 5 | - extension: 6 | last-update: Wed, 27 Jan 2021 11:44:41 UTC 7 | provider: minikube.sigs.k8s.io 8 | version: v1.17.0 9 | name: cluster_info 10 | server: https://192.168.49.2:8443 11 | name: minikube 12 | contexts: 13 | - context: 14 | cluster: minikube 15 | extensions: 16 | - extension: 17 | last-update: Wed, 27 Jan 2021 11:44:41 UTC 18 | provider: minikube.sigs.k8s.io 19 | version: v1.17.0 20 | name: context_info 21 | namespace: default 22 | user: minikube 23 | name: minikube 24 | current-context: minikube 25 | kind: Config 26 | preferences: {} 27 | users: 28 | - name: minikube 29 | user: 30 | password: secret 31 | username: admin 32 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.cluster-missmatch.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | certificate-authority: path/to/my/cafile 9 | server: https://horse.org:4443 10 | name: bad-name-cluster 11 | contexts: 12 | - context: 13 | cluster: horse-cluster 14 | namespace: chisel-ns 15 | user: green-user 16 | name: federal-context 17 | kind: Config 18 | users: 19 | - name: green-user 20 | user: 21 | password: secret 22 | username: admin -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.no-cluster.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | contexts: 7 | - context: 8 | cluster: horse-cluster 9 | namespace: chisel-ns 10 | user: green-user 11 | name: federal-context 12 | kind: Config 13 | users: 14 | - name: green-user 15 | user: 16 | password: secret 17 | username: admin -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.no-context-details.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | server: http://cow.org:8080 9 | name: cow-cluster 10 | - cluster: 11 | certificate-authority: assets/ca.crt 12 | server: https://horse.org:4443 13 | name: horse-cluster 14 | - cluster: 15 | insecure-skip-tls-verify: true 16 | server: https://pig.org:443 17 | name: pig-cluster 18 | contexts: 19 | - name: federal-context 20 | kind: Config 21 | users: 22 | - name: blue-user 23 | user: 24 | token: blue-token 25 | - name: green-user 26 | user: 27 | client-certificate: assets/client.crt 28 | client-key: assets/client.key 29 | - name: black-user 30 | user: 31 | token: black-token -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.no-context.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | server: http://cow.org:8080 9 | name: cow-cluster 10 | - cluster: 11 | certificate-authority: assets/ca.crt 12 | server: https://horse.org:4443 13 | name: horse-cluster 14 | - cluster: 15 | insecure-skip-tls-verify: true 16 | server: https://pig.org:443 17 | name: pig-cluster 18 | kind: Config 19 | users: 20 | - name: blue-user 21 | user: 22 | token: blue-token 23 | - name: green-user 24 | user: 25 | client-certificate: assets/client.crt 26 | client-key: assets/client.key 27 | - name: black-user 28 | user: 29 | token: black-token -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.no-credentials.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | certificate-authority: assets/ca.crt 9 | server: https://horse.org:4443 10 | name: horse-cluster 11 | contexts: 12 | - context: 13 | cluster: horse-cluster 14 | namespace: chisel-ns 15 | user: green-user 16 | name: federal-context 17 | kind: Config 18 | users: 19 | - name: green-user 20 | user: -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.no-current-context.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | clusters: 4 | - cluster: 5 | certificate-authority: assets/ca.crt 6 | server: https://horse.org:4443 7 | name: horse-cluster 8 | contexts: 9 | - context: 10 | cluster: horse-cluster 11 | namespace: chisel-ns 12 | user: green-user 13 | name: federal-context 14 | kind: Config 15 | users: 16 | - name: green-user 17 | user: 18 | password: secret 19 | username: admin -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.no-server.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | certificate-authority: path/to/my/cafile 9 | name: horse-cluster 10 | contexts: 11 | - context: 12 | cluster: horse-cluster 13 | namespace: chisel-ns 14 | user: green-user 15 | name: federal-context 16 | kind: Config 17 | users: 18 | - name: green-user 19 | user: 20 | password: secret 21 | username: admin -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.no-user.yml: -------------------------------------------------------------------------------- 1 | --- 2 | current-context: federal-context 3 | apiVersion: v1 4 | clusters: 5 | - cluster: 6 | certificate-authority: assets/ca.crt 7 | server: https://horse.org:4443 8 | name: horse-cluster 9 | contexts: 10 | - context: 11 | cluster: horse-cluster 12 | namespace: chisel-ns 13 | name: federal-context 14 | kind: Config -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.preferences-extensions.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Config 3 | preferences: 4 | colors: true 5 | extensions: 6 | - name: foo 7 | extension: 8 | foo: bar 9 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.tls-no-skip.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | insecure-skip-tls-verify: false 9 | server: https://horse.org:443 10 | name: horse-cluster 11 | contexts: 12 | - context: 13 | cluster: horse-cluster 14 | namespace: chisel-ns 15 | user: green-user 16 | name: federal-context 17 | kind: Config 18 | users: 19 | - name: green-user 20 | user: 21 | password: secret 22 | username: admin 23 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.tls-servername.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | server: https://horse.org:443 9 | tls-server-name: pony 10 | name: horse-cluster 11 | contexts: 12 | - context: 13 | cluster: horse-cluster 14 | namespace: chisel-ns 15 | user: green-user 16 | name: federal-context 17 | kind: Config 18 | users: 19 | - name: green-user 20 | user: 21 | password: secret 22 | username: admin 23 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.tls-skip-http.yml: -------------------------------------------------------------------------------- 1 | --- 2 | current-context: federal-context 3 | apiVersion: v1 4 | clusters: 5 | - cluster: 6 | server: http://horse.org 7 | name: horse-cluster 8 | contexts: 9 | - context: 10 | cluster: horse-cluster 11 | namespace: chisel-ns 12 | user: green-user 13 | name: federal-context 14 | kind: Config 15 | users: 16 | - name: green-user 17 | user: 18 | password: secret 19 | username: admin -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.tls-skip.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | insecure-skip-tls-verify: true 9 | server: https://horse.org:443 10 | name: horse-cluster 11 | contexts: 12 | - context: 13 | cluster: horse-cluster 14 | namespace: chisel-ns 15 | user: green-user 16 | name: federal-context 17 | kind: Config 18 | users: 19 | - name: green-user 20 | user: 21 | password: secret 22 | username: admin -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.user-not-found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | current-context: federal-context 3 | apiVersion: v1 4 | clusters: 5 | - cluster: 6 | certificate-authority: assets/ca.crt 7 | server: https://horse.org:4443 8 | name: horse-cluster 9 | contexts: 10 | - context: 11 | cluster: horse-cluster 12 | namespace: chisel-ns 13 | user: green-user 14 | name: federal-context 15 | kind: Config -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.user-oidc.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | certificate-authority: assets/ca.crt 9 | server: https://horse.org:4443 10 | name: horse-cluster 11 | contexts: 12 | - context: 13 | cluster: horse-cluster 14 | namespace: chisel-ns 15 | user: green-user 16 | name: federal-context 17 | kind: Config 18 | users: 19 | - name: green-user 20 | user: 21 | auth-provider: 22 | config: 23 | client-id: CLIENT_ID 24 | client-secret: CLIENT_SECRET 25 | id-token: ID_TOKEN 26 | idp-issuer-url: IDP_ISSUER_URL 27 | refresh-token: REFRESH_TOKEN 28 | name: oidc 29 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.user-pass.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | certificate-authority: assets/ca.crt 9 | server: https://horse.org:4443 10 | name: horse-cluster 11 | contexts: 12 | - context: 13 | cluster: horse-cluster 14 | namespace: chisel-ns 15 | user: green-user 16 | name: federal-context 17 | kind: Config 18 | users: 19 | - name: green-user 20 | user: 21 | password: secret 22 | username: admin 23 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.wildcard-ipv4.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | server: https://0.0.0.0:443 9 | name: horse-cluster 10 | contexts: 11 | - context: 12 | cluster: horse-cluster 13 | namespace: chisel-ns 14 | user: green-user 15 | name: federal-context 16 | kind: Config 17 | users: 18 | - name: green-user 19 | user: 20 | password: secret 21 | username: admin 22 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.wildcard-ipv6.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | server: https://[::]:443 9 | name: horse-cluster 10 | contexts: 11 | - context: 12 | cluster: horse-cluster 13 | namespace: chisel-ns 14 | user: green-user 15 | name: federal-context 16 | kind: Config 17 | users: 18 | - name: green-user 19 | user: 20 | password: secret 21 | username: admin 22 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/kubeconfig.wildcard-ipv6_2.yml: -------------------------------------------------------------------------------- 1 | # Sample file based on https://kubernetes.io/docs/tasks/access-application-cluster/authenticate-across-clusters-kubeconfig/ 2 | # WARNING: File includes minor fixes 3 | --- 4 | current-context: federal-context 5 | apiVersion: v1 6 | clusters: 7 | - cluster: 8 | server: https://[0:0:0:0:0:0:0:0]:443 9 | name: horse-cluster 10 | contexts: 11 | - context: 12 | cluster: horse-cluster 13 | namespace: chisel-ns 14 | user: green-user 15 | name: federal-context 16 | kind: Config 17 | users: 18 | - name: green-user 19 | user: 20 | password: secret 21 | username: admin 22 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/mock-gcloud.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | type %~dp0\gcloud-config-helper.json 3 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/mock-gcloud.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT=$(readlink -f "$0") 3 | SCRIPTPATH=$(dirname "$SCRIPT") 4 | OUTPUT_JSON=$SCRIPTPATH/gcloud-config-helper.json 5 | cat $OUTPUT_JSON 6 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/token1: -------------------------------------------------------------------------------- 1 | token1 2 | -------------------------------------------------------------------------------- /tests/KubernetesClient.Tests/assets/token2: -------------------------------------------------------------------------------- 1 | token2 2 | -------------------------------------------------------------------------------- /tests/SkipTestLogger/SkipTestLogger.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestPlatform.ObjectModel; 2 | using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | namespace k8s.E2E 8 | { 9 | // This TestLogger is to log test cases skipped by accident 10 | // when E2E test runs in github action 11 | 12 | [FriendlyName("SkipTestLogger")] 13 | [ExtensionUri("logger://Microsoft/TestPlatform/SkipTestLogger/v1")] 14 | public class SkipTestLogger : ITestLoggerWithParameters 15 | { 16 | public void Initialize(TestLoggerEvents events, Dictionary parameters) 17 | { 18 | if (parameters != null && parameters.TryGetValue("file", out var file)) 19 | { 20 | InnerInitialize(events, file); 21 | } 22 | else 23 | { 24 | throw new ArgumentNullException("file", "log file path must be set"); 25 | } 26 | } 27 | 28 | private static void InnerInitialize(TestLoggerEvents events, string file) 29 | { 30 | if (events == null) 31 | { 32 | throw new ArgumentNullException(nameof(events)); 33 | } 34 | 35 | Console.WriteLine($"using {file} for skipped test case log"); 36 | events.TestResult += (sender, args) => 37 | { 38 | using (var w = File.AppendText(file)) 39 | { 40 | if (args.Result.Outcome == TestOutcome.Skipped) 41 | { 42 | w.WriteLine(args.Result.DisplayName); 43 | } 44 | } 45 | }; 46 | } 47 | 48 | public void Initialize(TestLoggerEvents events, string testRunDirectory) 49 | { 50 | InnerInitialize(events, Path.Combine(testRunDirectory, "skip.log")); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/SkipTestLogger/SkipTestLogger.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "17.0", 4 | "publicReleaseRefSpec": [ 5 | "^refs/heads/master$", 6 | "^refs/tags/v\\d+\\.\\d+\\.\\d+" 7 | ], 8 | "cloudBuild": { 9 | "setVersionVariables": false 10 | } 11 | } 12 | --------------------------------------------------------------------------------