diff --git a/src/KubeClient/KubeClientConstants.cs b/src/KubeClient/KubeClientConstants.cs index 61d9099..e7603be 100644 --- a/src/KubeClient/KubeClientConstants.cs +++ b/src/KubeClient/KubeClientConstants.cs @@ -23,7 +23,7 @@ public static class KubeClientConstants public const string KubernetesServicePort = "KUBERNETES_SERVICE_PORT"; /// - /// Default path of mounted volume containing Kubernetes service account token and CA certificate + /// Default path of mounted volume containing Kubernetes service account token, CA certificate, and default namespace. /// public const string DefaultServiceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount"; } diff --git a/src/KubeClient/KubeClientOptions.cs b/src/KubeClient/KubeClientOptions.cs index 5292ac4..03c482b 100644 --- a/src/KubeClient/KubeClientOptions.cs +++ b/src/KubeClient/KubeClientOptions.cs @@ -188,7 +188,7 @@ public KubeClientOptions EnsureValid() /// Create new using pod-level configuration. /// /// - /// The location of the volume containing service account token and CA certificate + /// The location of the volume containing service account token, CA certificate, and default namespace. /// /// /// The configured . @@ -204,6 +204,8 @@ public static KubeClientOptions FromPodServiceAccount(string serviceAccountPath if (String.IsNullOrWhiteSpace(kubeServiceHost) || String.IsNullOrWhiteSpace(kubeServicePort)) throw new InvalidOperationException($"KubeApiClient.CreateFromPodServiceAccount can only be called when running in a Kubernetes Pod ({KubeClientConstants.KubernetesServiceHost} and/or {KubeClientConstants.KubernetesServicePort} environment variable is not defined)."); + string defaultNamespace = File.ReadAllText(Path.Combine(serviceAccountPath, "namespace")).Trim(); + string apiEndPoint = $"https://{kubeServiceHost}:{kubeServicePort}/"; string accessToken = File.ReadAllText(Path.Combine(serviceAccountPath, "token")); var kubeCACertificate = new X509Certificate2( @@ -215,7 +217,8 @@ public static KubeClientOptions FromPodServiceAccount(string serviceAccountPath ApiEndPoint = new Uri(apiEndPoint), AuthStrategy = KubeAuthStrategy.BearerToken, AccessToken = accessToken, - CertificationAuthorityCertificate = kubeCACertificate + CertificationAuthorityCertificate = kubeCACertificate, + KubeNamespace = defaultNamespace }; } } diff --git a/src/KubeClient/ResourceClients/EventClientV1.cs b/src/KubeClient/ResourceClients/EventClientV1.cs index fef6568..6cb1d96 100644 --- a/src/KubeClient/ResourceClients/EventClientV1.cs +++ b/src/KubeClient/ResourceClients/EventClientV1.cs @@ -130,7 +130,7 @@ static class Requests /// /// A collection-level Event (v1) request. /// - public static readonly HttpRequest Collection = KubeRequest.Create("/api/v1/namespaces/{Namespace}/events?labelSelector={LabelSelector?}&fieldSelector={fieldSelector?}&resourceVersion={ResourceVersion?}"); + public static readonly HttpRequest Collection = KubeRequest.Create("/api/v1/namespaces/{Namespace}/events?labelSelector={LabelSelector?}&fieldSelector={FieldSelector?}&resourceVersion={ResourceVersion?}"); /// /// A get-by-name Event (v1) request. @@ -140,7 +140,7 @@ static class Requests /// /// A collection-level Event watch (v1) request. /// - public static readonly HttpRequest WatchCollection = KubeRequest.Create("/api/v1/watch/namespaces/{Namespace}/events?labelSelector={LabelSelector?}&fieldSelector={fieldSelector?}&resourceVersion={ResourceVersion?}"); + public static readonly HttpRequest WatchCollection = KubeRequest.Create("/api/v1/watch/namespaces/{Namespace}/events?labelSelector={LabelSelector?}&fieldSelector={FieldSelector?}&resourceVersion={ResourceVersion?}"); } } diff --git a/src/KubeClient/ResourceClients/PodClientV1.cs b/src/KubeClient/ResourceClients/PodClientV1.cs index 3ba8350..7c969a3 100644 --- a/src/KubeClient/ResourceClients/PodClientV1.cs +++ b/src/KubeClient/ResourceClients/PodClientV1.cs @@ -62,6 +62,9 @@ public async Task Get(string name, string kubeNamespace = null, Cancellat /// /// An optional Kubernetes label selector expression used to filter the Pods. /// + /// + /// An optional Kubernetes field selector expression used to filter the Pods. + /// /// /// The target Kubernetes namespace (defaults to ). /// @@ -71,13 +74,14 @@ public async Task Get(string name, string kubeNamespace = null, Cancellat /// /// A containing the Pods. /// - public async Task List(string labelSelector = null, string kubeNamespace = null, CancellationToken cancellationToken = default) + public async Task List(string labelSelector = null, string fieldSelector = null, string kubeNamespace = null, CancellationToken cancellationToken = default) { return await GetResourceList( Requests.Collection.WithTemplateParameters(new { Namespace = kubeNamespace ?? KubeClient.DefaultNamespace, - LabelSelector = labelSelector + LabelSelector = labelSelector, + FieldSelector = fieldSelector }), cancellationToken: cancellationToken ); @@ -89,22 +93,26 @@ public async Task List(string labelSelector = null, string kubeNamesp /// /// An optional Kubernetes label selector expression used to filter the Pods. /// + /// + /// An optional Kubernetes field selector expression used to filter the Pods. + /// /// /// The target Kubernetes namespace (defaults to ). /// /// /// An representing the event stream. /// - public IObservable> WatchAll(string labelSelector = null, string kubeNamespace = null) + public IObservable> WatchAll(string labelSelector = null, string fieldSelector = null, string kubeNamespace = null) { return ObserveEvents( Requests.Collection.WithTemplateParameters(new { Namespace = kubeNamespace ?? KubeClient.DefaultNamespace, LabelSelector = labelSelector, + FieldSelector = fieldSelector, Watch = true }), - operationDescription: $"watch all v1/Pods with label selector '{labelSelector ?? ""}' in namespace {kubeNamespace ?? KubeClient.DefaultNamespace}" + operationDescription: $"watch all v1/Pods with label selector '{labelSelector ?? ""}' and field selector '{fieldSelector ?? ""}' in namespace {kubeNamespace ?? KubeClient.DefaultNamespace}" ); } @@ -270,7 +278,7 @@ public static class Requests /// /// A collection-level Pod (v1) request. /// - public static readonly HttpRequest Collection = KubeRequest.Create("api/v1/namespaces/{Namespace}/pods?labelSelector={LabelSelector?}&watch={Watch?}"); + public static readonly HttpRequest Collection = KubeRequest.Create("api/v1/namespaces/{Namespace}/pods?labelSelector={LabelSelector?}&fieldSelector={FieldSelector?}&watch={Watch?}"); /// /// A get-by-name Pod (v1) request. @@ -313,6 +321,9 @@ public interface IPodClientV1 /// /// An optional Kubernetes label selector expression used to filter the Pods. /// + /// + /// An optional Kubernetes field selector expression used to filter the Pods. + /// /// /// The target Kubernetes namespace (defaults to ). /// @@ -322,7 +333,7 @@ public interface IPodClientV1 /// /// A containing the Pods. /// - Task List(string labelSelector = null, string kubeNamespace = null, CancellationToken cancellationToken = default); + Task List(string labelSelector = null, string fieldSelector = null, string kubeNamespace = null, CancellationToken cancellationToken = default); /// /// Watch for events relating to Pods. @@ -330,13 +341,16 @@ public interface IPodClientV1 /// /// An optional Kubernetes label selector expression used to filter the Pods. /// + /// + /// An optional Kubernetes field selector expression used to filter the Pods. + /// /// /// The target Kubernetes namespace (defaults to ). /// /// /// An representing the event stream. /// - IObservable> WatchAll(string labelSelector = null, string kubeNamespace = null); + IObservable> WatchAll(string labelSelector = null, string fieldSelector = null, string kubeNamespace = null); /// /// Get the combined logs for the Pod with the specified name.