├── doc
├── index.md
├── CONTRIBUTING.md
├── toc.yml
├── .gitignore
└── docfx.json
├── tests
├── KubernetesClient.Tests
│ ├── assets
│ │ ├── token1
│ │ ├── token2
│ │ ├── mock-gcloud.cmd
│ │ ├── mock-gcloud.sh
│ │ ├── kubeconfig.preferences-extensions.yml
│ │ ├── kubeconfig.no-user.yml
│ │ ├── kubeconfig.user-not-found.yml
│ │ ├── elliptic-client.key
│ │ ├── kubeconfig.tls-skip-http.yml
│ │ ├── kubeconfig.no-current-context.yml
│ │ ├── kubeconfig.as-user-extra.yml
│ │ ├── kubeconfig.no-cluster.yml
│ │ ├── kubeconfig.no-credentials.yml
│ │ ├── kubeconfig.wildcard-ipv6.yml
│ │ ├── kubeconfig.no-server.yml
│ │ ├── kubeconfig.wildcard-ipv4.yml
│ │ ├── kubeconfig.wildcard-ipv6_2.yml
│ │ ├── kubeconfig.tls-servername.yml
│ │ ├── kubeconfig.tls-skip.yml
│ │ ├── kubeconfig.tls-no-skip.yml
│ │ ├── kubeconfig.user-pass.yml
│ │ ├── kubeconfig.cluster-missmatch.yml
│ │ ├── gcloud-config-helper.json
│ │ ├── elliptic.crt
│ │ ├── kubeconfig.cluster-extensions.yml
│ │ ├── kubeconfig.user-oidc.yml
│ │ ├── kubeconfig.no-context.yml
│ │ ├── kubeconfig.no-context-details.yml
│ │ ├── ca2.crt
│ │ ├── ca.crt
│ │ ├── ca-bundle-root.crt
│ │ ├── ca-bundle-intermediate.crt
│ │ ├── client.crt
│ │ ├── ca-data.txt
│ │ ├── client-certificate-data.txt
│ │ └── client.key
│ ├── AssemblyInfo.cs
│ ├── OperatingSystems.cs
│ ├── ItemsEnumTests.cs
│ ├── UtilityTests.cs
│ ├── IntOrStringTests.cs
│ ├── TokenFileAuthTests.cs
│ ├── OperatingSystemDependentFactAttribute.cs
│ ├── ExternalExecutionTests.cs
│ ├── Mock
│ │ ├── MockWebSocketBuilder.cs
│ │ └── Server
│ │ │ └── Startup.cs
│ ├── TaskAssert.cs
│ └── KubernetesClient.Tests.csproj
├── E2E.Tests
│ ├── Onebyone.cs
│ ├── MinikubeFactAttribute.cs
│ ├── KubectlTests.cs
│ └── E2E.Tests.csproj
├── SkipTestLogger
│ └── SkipTestLogger.csproj
├── Kubectl.Tests
│ ├── KubectlTests.cs
│ ├── Kubectl.Tests.csproj
│ └── KubectlTests.Version.cs
├── E2E.Aot.Tests
│ └── E2E.Aot.Tests.csproj
└── KubernetesClient.Classic.Tests
│ └── KubernetesClient.Classic.Tests.csproj
├── logo.png
├── .devcontainer
└── devcontainer.json
├── csharp.settings
├── examples
├── yaml
│ ├── yaml.csproj
│ └── Program.cs
├── resize
│ ├── resize.csproj
│ └── Program.cs
├── exec
│ ├── exec.csproj
│ └── Exec.cs
├── logs
│ ├── logs.csproj
│ └── Logs.cs
├── attach
│ ├── attach.csproj
│ └── Attach.cs
├── generic
│ ├── generic.csproj
│ └── Generic.cs
├── labels
│ ├── labels.csproj
│ └── PodList.cs
├── simple
│ ├── simple.csproj
│ └── PodList.cs
├── aks-kubelogin
│ ├── aks-kubelogin.csproj
│ ├── README.md
│ └── Program.cs
├── clientset
│ ├── clientset.csproj
│ └── Program.cs
├── patch
│ ├── patch.csproj
│ └── Program.cs
├── portforward
│ └── portforward.csproj
├── watch
│ ├── watch.csproj
│ └── Program.cs
├── namespace
│ └── namespace.csproj
├── customResource
│ ├── config
│ │ ├── yaml-cr-instance.yaml
│ │ └── crd.yaml
│ ├── customResource.csproj
│ ├── cResource.cs
│ ├── Utils.cs
│ ├── CustomResourceDefinition.cs
│ └── README.md
├── webApiDependencyInjection
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── webApiDependencyInjection.csproj
│ ├── Program.cs
│ └── Controllers
│ │ ├── ExampleDependencyInjectionOnMethodController.cs
│ │ └── ExampleDependencyInjectionOnConstructorController.cs
├── workerServiceDependencyInjection
│ ├── appsettings.json
│ ├── appsettings.Development.json
│ ├── workerServiceDependencyInjection.csproj
│ ├── Program.cs
│ └── Worker.cs
├── cp
│ └── cp.csproj
├── Directory.Build.props
├── metrics
│ └── metrics.csproj
├── Directory.Build.targets
├── csrApproval
│ └── csrApproval.csproj
├── restart
│ └── restart.csproj
├── patch-aot
│ ├── patch-aot.csproj
│ └── Program.cs
├── aot
│ ├── aot.csproj
│ └── Program.cs
└── openTelemetryConsole
│ ├── openTelemetryConsole.csproj
│ └── Program.cs
├── code-of-conduct.md
├── global.json
├── OWNERS
├── src
├── LibKubernetesGenerator
│ ├── IScriptObjectHelper.cs
│ ├── generators
│ │ └── LibKubernetesGenerator
│ │ │ └── LibKubernetesGenerator.csproj
│ ├── VersionGenerator.cs
│ ├── templates
│ │ ├── IKubernetes.cs.template
│ │ ├── AbstractKubernetes.cs.template
│ │ ├── ClientSet.cs.template
│ │ ├── SourceGenerationContext.cs.template
│ │ ├── GroupClient.cs.template
│ │ └── Model.cs.template
│ ├── EmbedResource.cs
│ ├── ScriptObjectFactory.cs
│ ├── UtilHelper.cs
│ ├── SourceGenerationContextGenerator.cs
│ └── GeneratorExecutionContextExt.cs
├── KubernetesClient.Aot
│ ├── KubeConfigModels
│ │ ├── StaticContext.cs
│ │ ├── ExecCredentialResponseContext.cs
│ │ ├── User.cs
│ │ ├── Context.cs
│ │ ├── Cluster.cs
│ │ ├── AuthProvider.cs
│ │ ├── ContextDetails.cs
│ │ ├── ExecCredentialResponse.cs
│ │ ├── ExternalExecution.cs
│ │ └── ClusterEndpoint.cs
│ ├── Global.cs
│ └── V1PatchJsonConverter.cs
├── KubernetesClient
│ ├── IKubernetes.cs
│ ├── Models
│ │ ├── GeneratedModelVersion.cs
│ │ ├── V1PodTemplateSpec.cs
│ │ ├── ISpec.cs
│ │ ├── IMetadata.cs
│ │ ├── IStatus.cs
│ │ ├── ContainerMetrics.cs
│ │ ├── IItems.cs
│ │ ├── V1Status.cs
│ │ ├── V1PatchJsonConverter.cs
│ │ ├── KubernetesDateTimeYamlConverter.cs
│ │ ├── KubernetesEntityAttribute.cs
│ │ ├── PodMetricsList.cs
│ │ ├── NodeMetricsList.cs
│ │ ├── IntOrString.cs
│ │ ├── NodeMetrics.cs
│ │ ├── PodMetrics.cs
│ │ ├── IntOrStringJsonConverter.cs
│ │ ├── IntOrStringYamlConverter.cs
│ │ ├── ResourceQuantityJsonConverter.cs
│ │ ├── ResourceQuantityYamlConverter.cs
│ │ ├── V1Patch.cs
│ │ ├── V1Status.ObjectView.cs
│ │ └── KubernetesList.cs
│ ├── Global.cs
│ ├── GeneratedApiVersion.cs
│ ├── ClientSets
│ │ ├── ClientSet.cs
│ │ └── ResourceClient.cs
│ ├── LeaderElection
│ │ ├── LeaderElectionConfig.cs
│ │ └── ResourceLock
│ │ │ ├── MetaObjectAnnotationLock.cs
│ │ │ ├── MultiLock.cs
│ │ │ ├── EndpointsLock.cs
│ │ │ └── ConfigMapLock.cs
│ ├── Exceptions
│ │ ├── KubeConfigException.cs
│ │ └── KubernetesClientException.cs
│ ├── KubeConfigModels
│ │ ├── User.cs
│ │ ├── Cluster.cs
│ │ ├── NamedExtension.cs
│ │ ├── AuthProvider.cs
│ │ ├── ExecCredentialResponse.cs
│ │ ├── Context.cs
│ │ ├── ContextDetails.cs
│ │ └── ExternalExecution.cs
│ ├── StreamType.cs
│ ├── Utilities.cs
│ ├── KubernetesClient.csproj
│ ├── Authentication
│ │ ├── ITokenProvider.cs
│ │ ├── ServiceClientCredentials.cs
│ │ ├── ExecTokenProvider.cs
│ │ └── StringTokenProvider.cs
│ ├── ExecAsyncCallback.cs
│ ├── FloatEmitter.cs
│ ├── SourceGenerationContext.cs
│ ├── Autorest
│ │ ├── HttpExtensions.cs
│ │ ├── HttpRequestMessageWrapper.cs
│ │ └── HttpResponseMessageWrapper.cs
│ ├── IKubernetes.Exec.cs
│ ├── FileSystem.cs
│ ├── Extensions.cs
│ ├── KubernetesObject.cs
│ └── ChannelIndex.cs
├── KubernetesClient.Classic
│ ├── IsExternalInit.cs
│ ├── Global.cs
│ └── Kubernetes.Websocket.Netstandard.cs
├── KubernetesClient.Kubectl
│ ├── Beta
│ │ ├── AsyncKubectl.cs
│ │ ├── Kubectl.cs
│ │ ├── Kubectl.Version.cs
│ │ ├── Kubectl.Cordon.cs
│ │ ├── Kubectl.Delete.cs
│ │ ├── AsyncKubectl.Version.cs
│ │ ├── AsyncKubectl.Cordon.cs
│ │ ├── AsyncKubectl.Delete.cs
│ │ ├── Kubectl.Top.cs
│ │ └── Kubectl.Patch.cs
│ └── KubernetesClient.Kubectl.csproj
└── nuget.proj
├── Directory.Build.targets
├── nuget.config
├── .gitignore
├── kubernetes-client.proj
├── version.json
├── stylecop.json
├── SECURITY_CONTACTS
├── .github
├── ISSUE_TEMPLATE
│ └── bug_report.md
├── workflows
│ ├── draft.yaml
│ ├── docfx.yaml
│ └── nuget.yaml
└── dependabot.yml
├── .gitattributes
└── CONTRIBUTING.md
/doc/index.md:
--------------------------------------------------------------------------------
1 | ../README.md
--------------------------------------------------------------------------------
/doc/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ../CONTRIBUTING.md
--------------------------------------------------------------------------------
/tests/KubernetesClient.Tests/assets/token1:
--------------------------------------------------------------------------------
1 | token1
2 |
--------------------------------------------------------------------------------
/tests/KubernetesClient.Tests/assets/token2:
--------------------------------------------------------------------------------
1 | token2
2 |
--------------------------------------------------------------------------------
/doc/toc.yml:
--------------------------------------------------------------------------------
1 | - name: API Documentation
2 | href: api/k8s.yml
3 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kubernetes-client/csharp/HEAD/logo.png
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "image": "mcr.microsoft.com/dotnet/sdk:8.0"
3 | }
--------------------------------------------------------------------------------
/tests/KubernetesClient.Tests/assets/mock-gcloud.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | type %~dp0\gcloud-config-helper.json
3 |
--------------------------------------------------------------------------------
/csharp.settings:
--------------------------------------------------------------------------------
1 | export KUBERNETES_BRANCH=v1.34.0
2 | export CLIENT_VERSION=0.0.1
3 | export PACKAGE_NAME=k8s
4 |
--------------------------------------------------------------------------------
/tests/KubernetesClient.Tests/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 |
3 | [assembly: CollectionBehavior(DisableTestParallelization = true)]
4 |
--------------------------------------------------------------------------------
/examples/yaml/yaml.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 |
5 |
--------------------------------------------------------------------------------
/examples/resize/resize.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 |
5 |
--------------------------------------------------------------------------------
/examples/exec/exec.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/logs/logs.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/attach/attach.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/generic/generic.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/labels/labels.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/simple/simple.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/aks-kubelogin/aks-kubelogin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 |
5 |
--------------------------------------------------------------------------------
/examples/clientset/clientset.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/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/watch/watch.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | ###############
2 | # folder #
3 | ###############
4 | /**/DROP/
5 | /**/TEMP/
6 | /**/packages/
7 | /**/bin/
8 | /**/obj/
9 | _site
10 |
11 | api
--------------------------------------------------------------------------------
/examples/namespace/namespace.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/webApiDependencyInjection/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/workerServiceDependencyInjection/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.Hosting.Lifetime": "Information"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/workerServiceDependencyInjection/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.Hosting.Lifetime": "Information"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/webApiDependencyInjection/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*"
9 | }
10 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/KubernetesClient/IKubernetes.cs:
--------------------------------------------------------------------------------
1 | namespace k8s;
2 |
3 | public partial interface IKubernetes : IDisposable
4 | {
5 | ///
6 | /// The base URI of the service.
7 | ///
8 | Uri BaseUri { get; set; }
9 | }
10 |
--------------------------------------------------------------------------------
/examples/cp/cp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/KubernetesClient.Classic/IsExternalInit.cs:
--------------------------------------------------------------------------------
1 | // IntOrString.cs(7,36): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsExternalInit' is not defined or imported
2 | namespace System.Runtime.CompilerServices
3 | {
4 | internal static class IsExternalInit { }
5 | }
--------------------------------------------------------------------------------
/src/KubernetesClient.Aot/KubeConfigModels/ExecCredentialResponseContext.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.KubeConfigModels
2 | {
3 | [JsonSerializable(typeof(ExecCredentialResponse))]
4 | internal partial class ExecCredentialResponseContext : JsonSerializerContext
5 | {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/.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
--------------------------------------------------------------------------------
/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.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 |
--------------------------------------------------------------------------------
/examples/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | net9.0
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/customResource/customResource.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/kubernetes-client.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/metrics/metrics.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/tests/SkipTestLogger/SkipTestLogger.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/LibKubernetesGenerator/generators/LibKubernetesGenerator/LibKubernetesGenerator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | $(DefineConstants);GENERATE_BASIC;
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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 record V1PodTemplateSpec : IMetadata
8 | {
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/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/nuget.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/webApiDependencyInjection/webApiDependencyInjection.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | enable
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/csrApproval/csrApproval.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/restart/restart.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "18.0",
4 | "publicReleaseRefSpec": [
5 | "^refs/heads/master$",
6 | "^refs/tags/v\\d+\\.\\d+\\.\\d+"
7 | ],
8 | "cloudBuild": {
9 | "setVersionVariables": false
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/examples/workerServiceDependencyInjection/workerServiceDependencyInjection.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | enable
5 | enable
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/patch-aot/patch-aot.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | enable
5 | enable
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/examples/aot/aot.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | enable
5 | enable
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/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/openTelemetryConsole/openTelemetryConsole.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/LibKubernetesGenerator/templates/IKubernetes.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 IKubernetes
12 | {
13 | {{for group in groups}}
14 | I{{group}}Operations {{group}} { get; }
15 | {{end}}
16 | }
--------------------------------------------------------------------------------
/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.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
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/ISpec.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models;
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 |
--------------------------------------------------------------------------------
/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/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.Kubectl/KubernetesClient.Kubectl.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0;net9.0;net10.0
5 | enable
6 | enable
7 | k8s.kubectl
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/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/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 | public partial class SourceGenerationContext : JsonSerializerContext
12 | {
13 | }
14 | }
15 | #endif
16 |
--------------------------------------------------------------------------------
/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/Models/IMetadata.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models;
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.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.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.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | tg123
15 |
--------------------------------------------------------------------------------
/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.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
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/IStatus.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
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 |
--------------------------------------------------------------------------------
/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.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.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
--------------------------------------------------------------------------------
/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/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/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/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.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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.Kubectl/Beta/Kubectl.Delete.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.kubectl.beta;
2 |
3 | public partial class Kubectl
4 | {
5 | ///
6 | /// Delete a Kubernetes resource by name.
7 | ///
8 | /// The type of Kubernetes resource to delete.
9 | /// The name of the resource.
10 | /// The namespace of the resource (for namespaced resources). Optional.
11 | /// The deleted resource.
12 | public T Delete(string name, string? @namespace = null)
13 | where T : IKubernetesObject
14 | {
15 | return client.DeleteAsync(name, @namespace).GetAwaiter().GetResult();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/KubernetesClient/Models/IItems.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models;
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 |
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/V1Status.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 |
3 | namespace k8s.Models
4 | {
5 | public partial record 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.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/KubernetesClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0;net9.0;net10.0
5 | k8s
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/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/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.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.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
--------------------------------------------------------------------------------
/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/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/Models/V1PatchJsonConverter.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | public 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/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 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/src/KubernetesClient.Aot/V1PatchJsonConverter.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | public 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 | throw new NotSupportedException("only string json patch is supported");
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/KubernetesDateTimeYamlConverter.cs:
--------------------------------------------------------------------------------
1 | using YamlDotNet.Core;
2 | using YamlDotNet.Serialization;
3 |
4 | namespace k8s.Models;
5 |
6 | public sealed class KubernetesDateTimeYamlConverter : IYamlTypeConverter
7 | {
8 | private static readonly KubernetesDateTimeOffsetYamlConverter OffsetConverter = new();
9 |
10 | public bool Accepts(Type type) => type == typeof(DateTime);
11 |
12 | public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
13 | {
14 | var dto = (DateTimeOffset)OffsetConverter.ReadYaml(parser, typeof(DateTimeOffset), rootDeserializer);
15 | return dto.DateTime;
16 | }
17 |
18 | public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
19 | {
20 | var date = new DateTimeOffset((DateTime)value);
21 | OffsetConverter.WriteYaml(emitter, date, typeof(DateTimeOffset), serializer);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 record CResourceSpec
23 | {
24 | [JsonPropertyName("cityName")]
25 | public string CityName { get; set; }
26 | }
27 |
28 | public record CResourceStatus : V1Status
29 | {
30 | [JsonPropertyName("temperature")]
31 | public string Temperature { get; set; }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/doc/docfx.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": [
3 | {
4 | "src": [
5 | {
6 | "files": [
7 | "KubernetesClient/bin/Release/net8.0/KubernetesClient.dll"
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 | "CONTRIBUTING.md",
24 | "toc.yml"
25 | ]
26 | }
27 | ],
28 | "dest": "_site",
29 | "globalMetadataFiles": [],
30 | "fileMetadataFiles": [],
31 | "template": [
32 | "default"
33 | ],
34 | "postProcessors": [],
35 | "markdownEngineName": "markdig",
36 | "noLangKeyword": false,
37 | "keepFileLink": false,
38 | "cleanupCacheHistory": false,
39 | "disableGitFeatures": false
40 | }
41 | }
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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@v6
17 | with:
18 | fetch-depth: 0
19 |
20 | - name: Setup dotnet
21 | uses: actions/setup-dotnet@v5
22 | with:
23 | dotnet-version: |
24 | 8.0.x
25 | 9.0.x
26 | 10.0.x
27 |
28 | - name: dotnet restore
29 | run: dotnet restore --verbosity minimal --configfile nuget.config
30 |
31 | - name: dotnet test
32 | run: dotnet test
33 |
34 | - uses: dotnet/nbgv@master
35 | with:
36 | setAllVars: true
37 |
38 | - name: create release
39 | shell: pwsh
40 | env:
41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42 | run: |
43 | gh release create -d --generate-notes v$env:NBGV_NuGetPackageVersion
44 |
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/IntOrString.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | [JsonConverter(typeof(IntOrStringJsonConverter))]
4 | public class IntOrString
5 | {
6 | public string Value { get; private init; }
7 |
8 | public static implicit operator IntOrString(int v)
9 | {
10 | return Convert.ToString(v);
11 | }
12 |
13 | public static implicit operator IntOrString(long v)
14 | {
15 | return Convert.ToString(v);
16 | }
17 |
18 | public static implicit operator string(IntOrString v)
19 | {
20 | return v?.Value;
21 | }
22 |
23 | public static implicit operator IntOrString(string v)
24 | {
25 | return new IntOrString { Value = v };
26 | }
27 |
28 | public override string ToString()
29 | {
30 | return Value;
31 | }
32 |
33 | public int ToInt()
34 | {
35 | return int.Parse(Value);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | IntOrString intorstr = v;
14 |
15 | Assert.Equal("123", KubernetesJson.Serialize(intorstr));
16 | }
17 |
18 | {
19 | IntOrString 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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/examples/clientset/Program.cs:
--------------------------------------------------------------------------------
1 | using k8s;
2 | using k8s.Models;
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 | var 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 | var watch = clientSet.CoreV1.Pod.WatchListAsync("default");
26 | await foreach (var (_, item) in watch.ConfigureAwait(false))
27 | {
28 | System.Console.WriteLine(item.Metadata.Name);
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/E2E.Tests/E2E.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 | k8s.E2E
5 | net8.0;net9.0;net10.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/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/Kubectl.Tests/Kubectl.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0;net9.0;net10.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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | ```
--------------------------------------------------------------------------------
/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.Delete.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.kubectl.beta;
2 |
3 | public partial class AsyncKubectl
4 | {
5 | ///
6 | /// Delete a Kubernetes resource by name.
7 | ///
8 | /// The type of Kubernetes resource to delete.
9 | /// The name of the resource.
10 | /// The namespace of the resource (for namespaced resources). Optional.
11 | /// Cancellation token.
12 | /// The deleted resource.
13 | public async Task DeleteAsync(string name, string? @namespace = null, CancellationToken cancellationToken = default)
14 | where T : IKubernetesObject
15 | {
16 | var metadata = typeof(T).GetKubernetesTypeMetadata();
17 | using var genericClient = new GenericClient(client, metadata.Group, metadata.ApiVersion, metadata.PluralName, disposeClient: false);
18 |
19 | return @namespace != null
20 | ? await genericClient.DeleteNamespacedAsync(@namespace, name, cancellationToken).ConfigureAwait(false)
21 | : await genericClient.DeleteAsync(name, cancellationToken).ConfigureAwait(false);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/IntOrStringJsonConverter.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | public sealed class IntOrStringJsonConverter : JsonConverter
4 | {
5 | public override IntOrString 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, IntOrString 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/SourceGenerationContext.cs:
--------------------------------------------------------------------------------
1 | using static k8s.KubernetesJson;
2 | using static k8s.Models.V1Status;
3 |
4 | namespace k8s;
5 |
6 | [JsonSourceGenerationOptions(
7 | DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
8 | PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
9 | UseStringEnumConverter = true,
10 | Converters = new[] { typeof(Iso8601TimeSpanConverter), typeof(KubernetesDateTimeConverter), typeof(KubernetesDateTimeOffsetConverter), typeof(V1StatusObjectViewConverter) })
11 | ]
12 | public partial class SourceGenerationContext : JsonSerializerContext
13 | {
14 | }
15 |
16 | ///
17 | /// Used by V1Status in order to avoid the recursive loop as SourceGenerationContext contains V1StatusObjectViewConverter
18 | ///
19 | [JsonSerializable(typeof(V1Status))]
20 | [JsonSourceGenerationOptions(
21 | DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
22 | PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
23 | UseStringEnumConverter = true,
24 | Converters = new[] { typeof(Iso8601TimeSpanConverter), typeof(KubernetesDateTimeConverter), typeof(KubernetesDateTimeOffsetConverter) })
25 | ]
26 | public partial class StatusSourceGenerationContext : JsonSerializerContext
27 | {
28 | }
29 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/KubernetesClient.Kubectl/Beta/Kubectl.Top.cs:
--------------------------------------------------------------------------------
1 | using k8s.Models;
2 |
3 | namespace k8s.kubectl.beta;
4 |
5 | public partial class Kubectl
6 | {
7 | ///
8 | /// Get top nodes sorted by CPU or memory usage.
9 | ///
10 | /// The metric to sort by ("cpu" or "memory"). Defaults to "cpu".
11 | /// A list of nodes with their metrics, sorted by the specified metric in descending order.
12 | public List> TopNodes(string metric = "cpu")
13 | {
14 | return client.TopNodesAsync(metric).GetAwaiter().GetResult();
15 | }
16 |
17 | ///
18 | /// Get top pods in a namespace sorted by CPU or memory usage.
19 | ///
20 | /// The namespace to get pod metrics from.
21 | /// The metric to sort by ("cpu" or "memory"). Defaults to "cpu".
22 | /// A list of pods with their metrics, sorted by the specified metric in descending order.
23 | public List> TopPods(string @namespace, string metric = "cpu")
24 | {
25 | return client.TopPodsAsync(@namespace, metric).GetAwaiter().GetResult();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/LibKubernetesGenerator/GeneratorExecutionContextExt.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.CodeAnalysis;
2 | using Microsoft.CodeAnalysis.Text;
3 | using Microsoft.CodeAnalysis.CSharp;
4 | using Scriban;
5 | using Scriban.Runtime;
6 | using System.Text;
7 |
8 | namespace LibKubernetesGenerator
9 | {
10 | internal static class GeneratorExecutionContextExt
11 | {
12 | public static void RenderToContext(this IncrementalGeneratorPostInitializationContext context, string templatefile, ScriptObject sc, string generatedfile)
13 | {
14 | var tc = new TemplateContext();
15 | tc.PushGlobal(sc);
16 | context.RenderToContext(templatefile, tc, generatedfile);
17 | }
18 |
19 | public static void RenderToContext(this IncrementalGeneratorPostInitializationContext context, string templatefile, TemplateContext tc, string generatedfile)
20 | {
21 | var template = Template.Parse(EmbedResource.GetResource(templatefile));
22 | var generated = template.Render(tc);
23 |
24 | var syntaxTree = CSharpSyntaxTree.ParseText(generated);
25 | var normalized = syntaxTree.GetRoot().NormalizeWhitespace().ToFullString();
26 | context.AddSource(generatedfile, SourceText.From(normalized, Encoding.UTF8));
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/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.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 | [JsonPropertyName("expirationTimestamp")]
12 | public DateTime? ExpirationTimestamp { get; set; }
13 | [JsonPropertyName("token")]
14 | public string? Token { get; set; }
15 | [JsonPropertyName("clientCertificateData")]
16 | public string? ClientCertificateData { get; set; }
17 | [JsonPropertyName("clientKeyData")]
18 | public string? ClientKeyData { get; set; }
19 | #nullable disable
20 |
21 | public bool IsValid()
22 | {
23 | return !string.IsNullOrEmpty(Token) ||
24 | (!string.IsNullOrEmpty(ClientCertificateData) && !string.IsNullOrEmpty(ClientKeyData));
25 | }
26 | }
27 |
28 | [JsonPropertyName("apiVersion")]
29 | public string ApiVersion { get; set; }
30 | [JsonPropertyName("kind")]
31 | public string Kind { get; set; }
32 | [JsonPropertyName("status")]
33 | public ExecStatus Status { get; set; }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/LibKubernetesGenerator/templates/Model.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.Models;
8 |
9 | ///
10 | /// {{ToXmlDoc def.description}}
11 | ///
12 | {{ if hasExt }}
13 | [KubernetesEntity(Group=KubeGroup, Kind=KubeKind, ApiVersion=KubeApiVersion, PluralName=KubePluralName)]
14 | {{ end }}
15 | public partial {{typ}} {{clz}} {{ if hasExt }} : {{ GetInterfaceName def }} {{ end }}
16 | {
17 | {{ if hasExt}}
18 | public const string KubeApiVersion = "{{ GetApiVersion def }}";
19 | public const string KubeKind = "{{ GetKind def }}";
20 | public const string KubeGroup = "{{ GetGroup def }}";
21 | public const string KubePluralName = "{{ GetPlural def }}";
22 | {{ end }}
23 |
24 | {{ for property in properties }}
25 | ///
26 | /// {{ToXmlDoc property.description}}
27 | ///
28 | [JsonPropertyName("{{property.name}}")]
29 | public {{ if property.IsRequired }} required {{ end }} {{GetDotNetType property}} {{GetDotNetName property.name "field"}} { get; set; }
30 | {{ end }}
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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(IntOrString);
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 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 = (IntOrString)value;
38 | emitter?.Emit(new YamlDotNet.Core.Events.Scalar(obj?.Value));
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/ResourceQuantityJsonConverter.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | public 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 null;
12 | case JsonTokenType.Number:
13 | if (reader.TryGetDouble(out var val))
14 | {
15 | return Convert.ToString(val);
16 | }
17 |
18 | return reader.GetDecimal();
19 | default:
20 | return 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 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.Kubectl/Beta/Kubectl.Patch.cs:
--------------------------------------------------------------------------------
1 | using k8s.Models;
2 |
3 | namespace k8s.kubectl.beta;
4 |
5 | public partial class Kubectl
6 | {
7 | ///
8 | /// Patch a cluster-scoped Kubernetes resource.
9 | ///
10 | /// The type of Kubernetes resource to patch.
11 | /// The patch to apply.
12 | /// The name of the resource.
13 | /// The patched resource.
14 | public T Patch(V1Patch patch, string name)
15 | where T : IKubernetesObject
16 | {
17 | return client.PatchAsync(patch, name).GetAwaiter().GetResult();
18 | }
19 |
20 | ///
21 | /// Patch a namespaced Kubernetes resource.
22 | ///
23 | /// The type of Kubernetes resource to patch.
24 | /// The patch to apply.
25 | /// The namespace of the resource.
26 | /// The name of the resource.
27 | /// The patched resource.
28 | public T PatchNamespaced(V1Patch patch, string @namespace, string name)
29 | where T : IKubernetesObject
30 | {
31 | return client.PatchNamespacedAsync(patch, @namespace, name).GetAwaiter().GetResult();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/assets/ca-data.txt:
--------------------------------------------------------------------------------
1 | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURERENDQWZTZ0F3SUJBZ0lSQUo5ZCtLeThkTDJVSzRjdXplMmo2WnN3RFFZSktvWklodmNOQVFFTEJRQXcKTHpFdE1Dc0dBMVVFQXhNa1lXRTBZVFV3T0RZdE0yVm1aaTAwWWpCa0xUbGxORGt0WmpNeVpXWXpabUpqWWpNNApNQjRYRFRFM01ESXlOakExTURRek5Gb1hEVEl5TURJeU5UQTFNRFF6TkZvd0x6RXRNQ3NHQTFVRUF4TWtZV0UwCllUVXdPRFl0TTJWbVppMDBZakJrTFRsbE5Ea3Raak15WldZelptSmpZak00TUlJQklqQU5CZ2txaGtpRzl3MEIKQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBM2dkandhdHNsdCsvQVpqV3hmbkNQeGZqMzNHUUxlOU00VU42VmEwRQpKd0FYL2R3L1ZVa0dvVjlDc3NKRUZMdEdTUnM2K2h0RTEvOUN3ak1USDh2WExKcURHTE9KdFQ5dW9sR2c2Q2k1ClBKNDNKelVLWmJlYVE4Z3hhZndzQjdQU05vTTJOYzROVm9lZzBVTUw0bndGeEhXeTNYWHlFZ0QxTWxTUnVrb3oKTTNoRUVxUjJNVFdrNm9KK3VJNFF4WVZWMnZuWXdXaEJwUDlDR3RWUTlyUW9MVFowcmFpOCtDYURBMVltTWRhbQpRYUVPdURlSFRqU2FYM2dyR0FBVVFWNWl6MC9qVVBuK3lJNm1iV0trbzFzNytPY1dZR2F1aDFaMzFYSjJsc0RTCnU4a3F0d215UEcyUVl2aUQ4YjNOWFAyY0dRK2EwZlpRZnBrbTF0U3IxQnhhaXdJREFRQUJveU13SVRBT0JnTlYKSFE4QkFmOEVCQU1DQWdRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQQpuVzFXVXlLbVJ0TlNzU1VzVFBSUnhFRzhhek9kdjdYeUhRL0R5VWNqWm9rUEJVVHY4VjdvNG96RHgyVHV6UEdYCmZ2YlMvT2g0VDd6ZlYxdjJadmU3dTBxelNiRTl5OGpsaDNxYXJEcEd5ZmlTamwycmhIOFBmay9sZGR0VFpVL04KSkVtYW5ReGl6R20xV2pCSklRSE5LZENneVIwN3A1c0MwNnR3K25YUytla1MxMlBUTG45WjBuRDBKVDdQSzRXQgpQc3ZXeDVXN0w5dnJIdVN5SGRSTkt5eEEvbWI1WHdXMDBkZUpmaHZub0p3ZWRYNDVKZVRiME5MczUzaURqVEU1CnRpdU03Z1RVSjlCcGZTL0gvYSt2SmovVWQ2bHM0QndrWmpUNHNhOTA1bnNzdnRqamlwZ1N5a0QzVkxCQ3VueTkKd1NnbE1vSnZNWmg0bC9FVFJPeFE3Zz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
2 |
--------------------------------------------------------------------------------
/examples/watch/Program.cs:
--------------------------------------------------------------------------------
1 | using k8s;
2 | using System;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | var config = KubernetesClientConfiguration.BuildConfigFromConfigFile();
7 |
8 | IKubernetes client = new Kubernetes(config);
9 |
10 | var podlistResp = client.CoreV1.WatchListNamespacedPodAsync("default");
11 |
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.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 | using (var podlistResp = client.CoreV1.WatchListNamespacedPod("default", onEvent: (type, item) =>
26 | {
27 | Console.WriteLine("==on watch event==");
28 | Console.WriteLine(type);
29 | Console.WriteLine(item.Metadata.Name);
30 | Console.WriteLine("==on watch event==");
31 | }))
32 | {
33 | Console.WriteLine("press ctrl + c to stop watching");
34 |
35 | var ctrlc = new ManualResetEventSlim(false);
36 | Console.CancelKeyPress += (sender, eventArgs) => ctrlc.Set();
37 | ctrlc.Wait();
38 | }
39 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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@v6
29 | with:
30 | fetch-depth: 0
31 |
32 | - name: Setup dotnet
33 | uses: actions/setup-dotnet@v5
34 | with:
35 | dotnet-version: |
36 | 8.0.x
37 | 9.0.x
38 | 10.0.x
39 |
40 | - name: Build
41 | run: dotnet build -c Release
42 |
43 | - uses: nunit/docfx-action@v4.1.0
44 | name: Build Documentation
45 | with:
46 | args: doc/docfx.json
47 |
48 | - name: Setup Pages
49 | uses: actions/configure-pages@v5
50 | - name: Upload artifact
51 | uses: actions/upload-pages-artifact@v4
52 | with:
53 | # Upload entire repository
54 | path: doc/_site
55 | - name: Deploy to GitHub Pages
56 | id: deployment
57 | uses: actions/deploy-pages@v4
58 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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/KubernetesClient.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 | k8s.Tests
5 | net8.0;net9.0;net10.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/Models/V1Patch.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | [JsonConverter(typeof(V1PatchJsonConverter))]
4 | public record 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 | [JsonPropertyName("content")]
35 | [JsonInclude]
36 | public object Content { get; private set; }
37 |
38 | public PatchType Type { get; private set; }
39 |
40 | public V1Patch(object body, PatchType type)
41 | {
42 | if (type == PatchType.Unknown)
43 | {
44 | throw new ArgumentException("patch type must be set", nameof(type));
45 | }
46 |
47 | Content = body ?? throw new ArgumentNullException(nameof(body), "object must be set");
48 | Type = type;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/src/KubernetesClient/Models/V1Status.ObjectView.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | public partial record V1Status
4 | {
5 | public sealed class V1StatusObjectViewConverter : JsonConverter
6 | {
7 | public override V1Status Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
8 | {
9 | using var doc = JsonDocument.ParseValue(ref reader);
10 | var ele = doc.RootElement.Clone();
11 |
12 | try
13 | {
14 | #if NET8_0_OR_GREATER
15 | return JsonSerializer.Deserialize(ele, StatusSourceGenerationContext.Default.V1Status);
16 | #else
17 | return ele.Deserialize();
18 | #endif
19 | }
20 | catch (JsonException)
21 | {
22 | // should be an object
23 | }
24 |
25 | return new V1Status { _original = ele, HasObject = true };
26 | }
27 |
28 | public override void Write(Utf8JsonWriter writer, V1Status value, JsonSerializerOptions options)
29 | {
30 | throw new NotImplementedException(); // will not send v1status to server
31 | }
32 | }
33 |
34 | private JsonElement _original;
35 |
36 | public bool HasObject { get; private set; }
37 |
38 | public T ObjectView()
39 | {
40 | #if NET8_0_OR_GREATER
41 | return KubernetesJson.Deserialize(_original);
42 | #else
43 | return _original.Deserialize();
44 | #endif
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/tests/KubernetesClient.Classic.Tests/KubernetesClient.Classic.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | false
4 | k8s.Tests
5 | net8.0;net9.0;net10.0
6 | net8.0;net9.0;net10.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/KubernetesClient.Tests/assets/client-certificate-data.txt:
--------------------------------------------------------------------------------
1 | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURrVENDQW5tZ0F3SUJBZ0lVTzlVTkdpbHhmSHpMbVJXcWU2dVMyRVZ1NVhVd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RURBT0JnTlZCQWdUQjFKbFpHMXZibVF4Q3pBSkJnTlZCQWNUQWxkQgpNUk13RVFZRFZRUURFd3ByZFdKbGNtNWxkR1Z6TUNBWERURTRNVEl3T0RBNU5URXdNRm9ZRHpJeE1UZ3hNVEUwCk1EazFNVEF3V2pCQk1Rc3dDUVlEVlFRR0V3SlZVekVRTUE0R0ExVUVDQk1IVW1Wa2JXOXVaREVMTUFrR0ExVUUKQnhNQ1YwRXhFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQgpEd0F3Z2dFS0FvSUJBUUM4WkVRS296SE8zOExmRzRpcHFYWnRLTzNxSENjL1Z1WjUxWnZSeWJuTnpCYU5iMk9oClM0cU1nNDF6cFdzL3dMQnk4ZndPclpoOHpHb28wbHllQXVCSlBPWFc5SmswMmhOc1Y3ZHBqYXBZWFMrSXJvN04KcUxhWDB5amQxWWllSWFlb3NtV2xib2ZpcDVzS3dzVUI3bGREeXJpQklBYTEwNlhhTng5ZG82UEh1TDNibStldwpiaWRoRTlNUFRHY2V5WW9rZ3pNbGppanordk0yUnN5Z05ncmR4VDhROC9GRER2ZndTRmZUaEZlYXIzckQvRkJGCmVYb0Y5MHp6cG1aZlphTDlyZ2NjQ0pzQ2JSZlpiellVVERRVHo2dStaUVhUdGlrbVMvQ3d2d0hXa0w3bGhQNXYKQU0yVFpETEJhQXQwOU14dGlORFNWaFFTWVR2QWpKRmU4SzJoQWdNQkFBR2pmekI5TUE0R0ExVWREd0VCL3dRRQpBd0lGb0RBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFRWUlLd1lCQlFVSEF3SXdEQVlEVlIwVEFRSC9CQUl3CkFEQWRCZ05WSFE0RUZnUVVuQmo0T3Y3MnFlWWJ5YjVYSHJma1pkazd6VUF3SHdZRFZSMGpCQmd3Rm9BVUxwemQKRlplYkR6N0RmZUNkZkJqNmNkUWJmNk13RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQU1CL1RDaElEbTNkeDA4SApJeXlFS2dYUHh1d3A1cTB5QkFoT0pUS1JOVXNpayt6ZVUyUGpibnV0M3B1WnBENkZoTGFKQUZPbTdsMHhkNU1ZCkFZOVloSy9wa1U3Rmw1TFg0MitxQzRqK05JdGhBbFM5clNtNkRvNlN1b3JRcjdNajErY0syTjFkZHBtRWZya3kKZXZnMm02aFB5YTFlV0hNanVCd250bkJmV2EzWHBWMWVGZVBvd21zY3R6UmRJYUh3WDM3Yit3c2JmbkppczRvTgo2bHk0THBQb2xtYld3ZTRnaEtPWXNuL3lMT3FrUGJMZVpLeU5yaWJpSGhSQTM0NUVHUGJleXNmSlNIWWFqMnBaCmE0VmRTRFhnT2JlM3Vtdk9keXVEaGl5RFJ3TFozbVJLWlpIR0lzZC9ORzRncWo3a0gzV2N2Wm5mSkVHMXY2cG0KQTZFYTJiRT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
--------------------------------------------------------------------------------
/.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@v6
14 | with:
15 | fetch-depth: 0
16 |
17 | - name: Setup dotnet
18 | uses: actions/setup-dotnet@v5
19 | with:
20 | dotnet-version: |
21 | 8.0.x
22 | 9.0.x
23 | 10.0.x
24 |
25 | - name: dotnet restore
26 | run: dotnet restore --verbosity minimal --configfile nuget.config
27 |
28 | - name: dotnet test
29 | run: dotnet test
30 |
31 | - name: dotnet pack
32 | run: dotnet pack -c Release src/nuget.proj -o pkg --include-symbols
33 |
34 | - name: dotnet nuget push
35 | run: |
36 | dotnet nuget push pkg\*.nupkg -s https://nuget.pkg.github.com/$env:GITHUB_REPOSITORY_OWNER -k ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
37 | dotnet nuget push pkg\*.nupkg -s https://www.nuget.org/ -k ${{ secrets.nuget_api_key }} --skip-duplicate
38 |
39 |
40 | ## Remove old versions of NuGet packages form github NuGet feed
41 | nuget-delete-old-packages:
42 | name: "Delete Old NuGet"
43 | needs: [nuget]
44 | strategy:
45 | matrix:
46 | nuget-package:
47 | - "KubernetesClient"
48 | - "KubernetesClient.Classic"
49 | runs-on: ubuntu-latest
50 | permissions:
51 | packages: write
52 |
53 | steps:
54 | - name: Delete old NuGet packages
55 | uses: actions/delete-package-versions@v5
56 | with:
57 | owner: ${{ env.GITHUB_REPOSITORY_OWNER }}
58 | token: ${{ secrets.GITHUB_TOKEN }}
59 | package-name: ${{ matrix.nuget-package }}
60 | package-type: nuget
61 | min-versions-to-keep: 10
62 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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.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/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/Models/KubernetesList.cs:
--------------------------------------------------------------------------------
1 | namespace k8s.Models
2 | {
3 | public class KubernetesList : IMetadata, IItems
4 | where T : IKubernetesObject
5 | {
6 | public KubernetesList(IList items, string apiVersion = default, string kind = default,
7 | V1ListMeta metadata = default)
8 | {
9 | ApiVersion = apiVersion;
10 | Items = items;
11 | Kind = kind;
12 | Metadata = metadata;
13 | }
14 |
15 | ///
16 | /// Gets or sets aPIVersion defines the versioned schema of this
17 | /// representation of an object. Servers should convert recognized
18 | /// schemas to the latest internal value, and may reject unrecognized
19 | /// values. More info:
20 | /// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
21 | ///
22 | [JsonPropertyName("apiVersion")]
23 | public string ApiVersion { get; set; }
24 |
25 | [JsonPropertyName("items")]
26 | public IList Items { get; set; }
27 |
28 | ///
29 | /// Gets or sets kind is a string value representing the REST resource
30 | /// this object represents. Servers may infer this from the endpoint
31 | /// the client submits requests to. Cannot be updated. In CamelCase.
32 | /// More info:
33 | /// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
34 | ///
35 | [JsonPropertyName("kind")]
36 | public string Kind { get; set; }
37 |
38 | ///
39 | /// Gets or sets standard object's metadata.
40 | ///
41 | [JsonPropertyName("metadata")]
42 | public V1ListMeta Metadata { get; set; }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/examples/resize/Program.cs:
--------------------------------------------------------------------------------
1 | using k8s;
2 | using k8s.Models;
3 | using System;
4 | using System.Collections.Generic;
5 |
6 |
7 | var config = KubernetesClientConfiguration.BuildDefaultConfig();
8 | var client = new Kubernetes(config);
9 |
10 |
11 | var pod = new V1Pod
12 | {
13 | Metadata = new V1ObjectMeta { Name = "nginx-pod" },
14 | Spec = new V1PodSpec
15 | {
16 | Containers =
17 | [
18 | new V1Container
19 | {
20 | Name = "nginx",
21 | Image = "nginx",
22 | Resources = new V1ResourceRequirements
23 | {
24 | Requests = new Dictionary()
25 | {
26 | ["cpu"] = "100m",
27 | },
28 | },
29 | },
30 | ],
31 | },
32 | };
33 | {
34 | var created = await client.CoreV1.CreateNamespacedPodAsync(pod, "default").ConfigureAwait(false);
35 | Console.WriteLine($"Created pod: {created.Metadata.Name}");
36 | }
37 |
38 | {
39 | var patchStr = @"
40 | {
41 | ""spec"": {
42 | ""containers"": [
43 | {
44 | ""name"": ""nginx"",
45 | ""resources"": {
46 | ""requests"": {
47 | ""cpu"": ""200m""
48 | }
49 | }
50 | }
51 | ]
52 | }
53 | }";
54 |
55 | var patch = await client.CoreV1.PatchNamespacedPodResizeAsync(new V1Patch(patchStr, V1Patch.PatchType.MergePatch), "nginx-pod", "default").ConfigureAwait(false);
56 |
57 | if (patch?.Spec?.Containers?.Count > 0 &&
58 | patch.Spec.Containers[0].Resources?.Requests != null &&
59 | patch.Spec.Containers[0].Resources.Requests.TryGetValue("cpu", out var cpuQty))
60 | {
61 | Console.WriteLine($"CPU request: {cpuQty}");
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------