diff --git a/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Get.cs b/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Get.cs new file mode 100644 index 000000000..bf290f8a1 --- /dev/null +++ b/src/KubernetesClient.Kubectl/Beta/AsyncKubectl.Get.cs @@ -0,0 +1,28 @@ +namespace k8s.kubectl.beta; + +public partial class AsyncKubectl +{ + /// + /// Get a Kubernetes resource by name. + /// + /// The type of Kubernetes resource to get. + /// The name of the resource. + /// The namespace of the resource (for namespaced resources). Optional. + /// Cancellation token. + /// The requested resource. + public async Task GetAsync(string name, string? @namespace = null, CancellationToken cancellationToken = default) + where T : IKubernetesObject + { + var metadata = typeof(T).GetKubernetesTypeMetadata(); + var genericClient = new GenericClient(client, metadata.Group, metadata.ApiVersion, metadata.PluralName, disposeClient: false); + + if (@namespace != null) + { + return await genericClient.ReadNamespacedAsync(@namespace, name, cancellationToken).ConfigureAwait(false); + } + else + { + return await genericClient.ReadAsync(name, cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/src/KubernetesClient.Kubectl/Beta/Kubectl.Get.cs b/src/KubernetesClient.Kubectl/Beta/Kubectl.Get.cs new file mode 100644 index 000000000..dda5acba4 --- /dev/null +++ b/src/KubernetesClient.Kubectl/Beta/Kubectl.Get.cs @@ -0,0 +1,17 @@ +namespace k8s.kubectl.beta; + +public partial class Kubectl +{ + /// + /// Get a Kubernetes resource by name. + /// + /// The type of Kubernetes resource to get. + /// The name of the resource. + /// The namespace of the resource (for namespaced resources). Optional. + /// The requested resource. + public T Get(string name, string? @namespace = null) + where T : IKubernetesObject + { + return client.GetAsync(name, @namespace).GetAwaiter().GetResult(); + } +} diff --git a/tests/Kubectl.Tests/KubectlTests.Get.cs b/tests/Kubectl.Tests/KubectlTests.Get.cs new file mode 100644 index 000000000..f2114f0f5 --- /dev/null +++ b/tests/Kubectl.Tests/KubectlTests.Get.cs @@ -0,0 +1,216 @@ +using k8s.E2E; +using k8s.kubectl.beta; +using k8s.Models; +using Xunit; + +namespace k8s.kubectl.Tests; + +public partial class KubectlTests +{ + [MinikubeFact] + public void GetNamespace() + { + using var kubernetes = MinikubeTests.CreateClient(); + var client = new Kubectl(kubernetes); + + // Get the default namespace (cluster-scoped resource, no namespace parameter) + var ns = client.Get("default"); + + Assert.NotNull(ns); + Assert.Equal("default", ns.Metadata.Name); + Assert.Equal("v1", ns.ApiVersion); + Assert.Equal("Namespace", ns.Kind); + } + + [MinikubeFact] + public void GetPod() + { + using var kubernetes = MinikubeTests.CreateClient(); + var client = new Kubectl(kubernetes); + var namespaceParameter = "default"; + var podName = "k8scsharp-e2e-get-pod"; + + // Create a test pod + var pod = new V1Pod + { + Metadata = new V1ObjectMeta + { + Name = podName, + NamespaceProperty = namespaceParameter, + }, + Spec = new V1PodSpec + { + Containers = new[] + { + new V1Container + { + Name = "test", + Image = "nginx:latest", + }, + }, + }, + }; + + try + { + kubernetes.CoreV1.CreateNamespacedPod(pod, namespaceParameter); + + // Get the pod using kubectl generic get + var retrievedPod = client.Get(podName, namespaceParameter); + + Assert.NotNull(retrievedPod); + Assert.Equal(podName, retrievedPod.Metadata.Name); + Assert.Equal(namespaceParameter, retrievedPod.Metadata.NamespaceProperty); + Assert.Equal("Pod", retrievedPod.Kind); + Assert.Equal("v1", retrievedPod.ApiVersion); + } + finally + { + // Cleanup + try + { + kubernetes.CoreV1.DeleteNamespacedPod(podName, namespaceParameter); + } + catch + { + // Ignore cleanup errors + } + } + } + + [MinikubeFact] + public void GetService() + { + using var kubernetes = MinikubeTests.CreateClient(); + var client = new Kubectl(kubernetes); + var namespaceParameter = "default"; + var serviceName = "k8scsharp-e2e-get-service"; + + // Create a test service + var service = new V1Service + { + Metadata = new V1ObjectMeta + { + Name = serviceName, + NamespaceProperty = namespaceParameter, + }, + Spec = new V1ServiceSpec + { + Ports = new[] + { + new V1ServicePort + { + Port = 80, + TargetPort = 80, + }, + }, + Selector = new Dictionary + { + { "app", "test" }, + }, + }, + }; + + try + { + kubernetes.CoreV1.CreateNamespacedService(service, namespaceParameter); + + // Get the service using kubectl generic get + var retrievedService = client.Get(serviceName, namespaceParameter); + + Assert.NotNull(retrievedService); + Assert.Equal(serviceName, retrievedService.Metadata.Name); + Assert.Equal(namespaceParameter, retrievedService.Metadata.NamespaceProperty); + Assert.Equal("Service", retrievedService.Kind); + Assert.Equal("v1", retrievedService.ApiVersion); + } + finally + { + // Cleanup + try + { + kubernetes.CoreV1.DeleteNamespacedService(serviceName, namespaceParameter); + } + catch + { + // Ignore cleanup errors + } + } + } + + [MinikubeFact] + public void GetDeployment() + { + using var kubernetes = MinikubeTests.CreateClient(); + var client = new Kubectl(kubernetes); + var namespaceParameter = "default"; + var deploymentName = "k8scsharp-e2e-get-deployment"; + + // Create a test deployment + var deployment = new V1Deployment + { + Metadata = new V1ObjectMeta + { + Name = deploymentName, + NamespaceProperty = namespaceParameter, + }, + Spec = new V1DeploymentSpec + { + Replicas = 1, + Selector = new V1LabelSelector + { + MatchLabels = new Dictionary + { + { "app", "test" }, + }, + }, + Template = new V1PodTemplateSpec + { + Metadata = new V1ObjectMeta + { + Labels = new Dictionary + { + { "app", "test" }, + }, + }, + Spec = new V1PodSpec + { + Containers = new[] + { + new V1Container + { + Name = "test", + Image = "nginx:latest", + }, + }, + }, + }, + }, + }; + + try + { + kubernetes.AppsV1.CreateNamespacedDeployment(deployment, namespaceParameter); + + // Get the deployment using kubectl generic get + var retrievedDeployment = client.Get(deploymentName, namespaceParameter); + + Assert.NotNull(retrievedDeployment); + Assert.Equal(deploymentName, retrievedDeployment.Metadata.Name); + Assert.Equal(namespaceParameter, retrievedDeployment.Metadata.NamespaceProperty); + Assert.Equal("Deployment", retrievedDeployment.Kind); + } + finally + { + // Cleanup + try + { + kubernetes.AppsV1.DeleteNamespacedDeployment(deploymentName, namespaceParameter); + } + catch + { + // Ignore cleanup errors + } + } + } +}