diff --git a/src/KubernetesClient.Util/KubernetesClient.Util.csproj b/src/KubernetesClient.Util/KubernetesClient.Util.csproj deleted file mode 100644 index febeee354..000000000 --- a/src/KubernetesClient.Util/KubernetesClient.Util.csproj +++ /dev/null @@ -1,42 +0,0 @@ - - - - 9.0 - The Kubernetes Project Authors - 2017 The Kubernetes Project Authors - Supprting utilities for the kubernetes open source container orchestrator client library. - - Apache-2.0 - https://github.com/kubernetes-client/csharp - https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png - kubernetes;docker;containers; - - netstandard2.1;net5.0 - k8s.Util - true - true - - - true - - - true - snupkg - true - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - - - - - - - - - - - - - - - - diff --git a/src/KubernetesClient/KubernetesClient.csproj b/src/KubernetesClient/KubernetesClient.csproj index f75a5a8e7..e93e33241 100644 --- a/src/KubernetesClient/KubernetesClient.csproj +++ b/src/KubernetesClient/KubernetesClient.csproj @@ -5,13 +5,6 @@ k8s - - - - - - - diff --git a/src/KubernetesClient/Util/Common/BadNotificationException.cs b/src/KubernetesClient/Util/Common/BadNotificationException.cs deleted file mode 100644 index aa5a5b58e..000000000 --- a/src/KubernetesClient/Util/Common/BadNotificationException.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace k8s.Util.Common -{ - public class BadNotificationException : Exception - { - public BadNotificationException() - { - } - - public BadNotificationException(string message) - : base(message) - { - } - } -} diff --git a/src/KubernetesClient/Util/Common/CallGeneratorParams.cs b/src/KubernetesClient/Util/Common/CallGeneratorParams.cs deleted file mode 100644 index fbdc6ac2d..000000000 --- a/src/KubernetesClient/Util/Common/CallGeneratorParams.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace k8s.Util.Common -{ - public class CallGeneratorParams - { - public bool Watch { get; } - public string ResourceVersion { get; } - public int? TimeoutSeconds { get; } - - public CallGeneratorParams(bool watch, string resourceVersion, int? timeoutSeconds) - { - Watch = watch; - ResourceVersion = resourceVersion; - TimeoutSeconds = timeoutSeconds; - } - } -} diff --git a/src/KubernetesClient/Util/Common/CollectionsExtensions.cs b/src/KubernetesClient/Util/Common/CollectionsExtensions.cs deleted file mode 100644 index 6e1b7a51a..000000000 --- a/src/KubernetesClient/Util/Common/CollectionsExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace k8s.Util.Common -{ - internal static class CollectionsExtensions - { - public static void AddRange(this HashSet hashSet, ICollection items) - { - if (items == null || hashSet == null) - { - return; - } - - foreach (var item in items) - { - hashSet.Add(item); - } - } - - internal static TValue ComputeIfAbsent(this IDictionary dictionary, TKey key, Func mappingFunction) - { - if (dictionary is null) - { - throw new ArgumentNullException(nameof(dictionary)); - } - - if (dictionary.TryGetValue(key, out var value)) - { - return value; - } - - if (mappingFunction == null) - { - throw new ArgumentNullException(nameof(mappingFunction)); - } - - var newKey = mappingFunction(key); - dictionary[key] = newKey; - return newKey; - } - } -} diff --git a/src/KubernetesClient/Util/Common/Config.cs b/src/KubernetesClient/Util/Common/Config.cs deleted file mode 100644 index f4609d841..000000000 --- a/src/KubernetesClient/Util/Common/Config.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace k8s.Util.Common -{ - public static class Config - { - public static string ServiceAccountCaPath => KubernetesClientConfiguration.ServiceAccountPath + "/ca.crt"; - public static string ServiceAccountTokenPath => KubernetesClientConfiguration.ServiceAccountPath + "/token"; - public static string ServiceAccountNamespacePath => KubernetesClientConfiguration.ServiceAccountPath + "/namespace"; - public static string EnvKubeconfig => "KUBECONFIG"; - public static string EnvServiceHost => "KUBERNETES_SERVICE_HOST"; - public static string EnvServicePort => "KUBERNETES_SERVICE_PORT"; - - // The last resort host to try - public static string DefaultFallbackHost => "http://localhost:8080"; - } -} diff --git a/src/KubernetesClient/Util/Common/Generic/GenericKubernetesApi.cs b/src/KubernetesClient/Util/Common/Generic/GenericKubernetesApi.cs deleted file mode 100644 index a9e6ebb7d..000000000 --- a/src/KubernetesClient/Util/Common/Generic/GenericKubernetesApi.cs +++ /dev/null @@ -1,647 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using k8s.Models; -using k8s.Util.Common.Generic.Options; -using k8s.Autorest; - -namespace k8s.Util.Common.Generic -{ - /// - /// - /// The Generic kubernetes api provides a unified client interface for not only the non-core-group - /// built-in resources from kubernetes but also the custom-resources models meet the following - /// requirements: - /// - /// 1. there's a `V1ObjectMeta` field in the model along with its getter/setter. 2. there's a - /// `V1ListMeta` field in the list model along with its getter/setter. - supports Json - /// serialization/deserialization. 3. the generic kubernetes api covers all the basic operations over - /// the custom resources including {get, list, watch, create, update, patch, delete}. - /// - /// - For kubernetes-defined failures, the server will return a {@link V1Status} with 4xx/5xx - /// code. The status object will be nested in {@link KubernetesApiResponse#getStatus()} - For the - /// other unknown reason (including network, JVM..), throws an unchecked exception. - /// - public class GenericKubernetesApi - { - private readonly string _apiGroup; - private readonly string _apiVersion; - private readonly string _resourcePlural; - private readonly IKubernetes _client; - - /// - /// Initializes a new instance of the class. - /// - /// the api group"> - /// the api version"> - /// the resource plural, e.g. "jobs""> - /// optional client"> - public GenericKubernetesApi(string apiGroup = default, string apiVersion = default, string resourcePlural = default, IKubernetes apiClient = default) - { - _apiGroup = apiGroup ?? throw new ArgumentNullException(nameof(apiGroup)); - _apiVersion = apiVersion ?? throw new ArgumentNullException(nameof(apiVersion)); - _resourcePlural = resourcePlural ?? throw new ArgumentNullException(nameof(resourcePlural)); - _client = apiClient ?? new Kubernetes(KubernetesClientConfiguration.BuildDefaultConfig()); - } - - /// - /// Get kubernetes object. - /// - /// the object type - /// the object name - /// the token - /// The object - public Task GetAsync(string name, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return GetAsync(name, new GetOptions(), cancellationToken); - } - - /// - /// Get kubernetes object under the namespaceProperty. - /// - /// the object type - /// the namespaceProperty - /// the name - /// the token - /// the kubernetes object - public Task GetAsync(string namespaceProperty, string name, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return GetAsync(namespaceProperty, name, new GetOptions(), cancellationToken); - } - - /// - /// List kubernetes object cluster-scoped. - /// - /// the object type - /// the token - /// the kubernetes object - public Task ListAsync(CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return ListAsync(new ListOptions(), cancellationToken); - } - - /// - /// List kubernetes object under the namespaceProperty. - /// - /// the object type - /// the namespace - /// the token - /// the kubernetes object - public Task ListAsync(string namespaceProperty, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return ListAsync(namespaceProperty, new ListOptions(), cancellationToken); - } - - /// - /// Create kubernetes object, if the namespaceProperty in the object is present, it will send a - /// namespaceProperty-scoped requests, vice versa. - /// - /// the object type - /// the object - /// the token - /// the kubernetes object - public Task CreateAsync(T obj, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return CreateAsync(obj, new CreateOptions(), cancellationToken); - } - - /// - /// Create kubernetes object, if the namespaceProperty in the object is present, it will send a - /// namespaceProperty-scoped requests, vice versa. - /// - /// the object - /// the token - /// the object type - /// the kubernetes object - public Task UpdateAsync(T obj, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return UpdateAsync(obj, new UpdateOptions(), cancellationToken); - } - - /// - /// Patch kubernetes object. - /// - /// the name - /// the string patch content - /// the token - /// the object type - /// the kubernetes object - public Task PatchAsync(string name, object patch, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return PatchAsync(name, patch, new PatchOptions(), cancellationToken); - } - - /// - /// Patch kubernetes object under the namespaceProperty. - /// - /// the namespaceProperty - /// the name - /// the string patch content - /// the token - /// the object type - /// the kubernetes object - public Task PatchAsync(string namespaceProperty, string name, object patch, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return PatchAsync(namespaceProperty, name, patch, new PatchOptions(), cancellationToken); - } - - /// - /// Delete kubernetes object. - /// - /// the name - /// the token - /// the object type - /// the kubernetes object - public Task DeleteAsync(string name, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return DeleteAsync(name, new V1DeleteOptions(), cancellationToken); - } - - /// - /// Delete kubernetes object under the namespaceProperty. - /// - /// the namespaceProperty - /// the name - /// the token - /// the object type - /// the kubernetes object - public Task DeleteAsync(string namespaceProperty, string name, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return DeleteAsync(namespaceProperty, name, new V1DeleteOptions(), cancellationToken); - } - - /// - /// Creates a cluster-scoped Watch on the resource. - /// - /// action on event - /// action on error - /// action on closed - /// the token - /// the object type - /// the watchable - public Watcher Watch(Action onEvent, Action onError = default, Action onClosed = default, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return Watch(new ListOptions(), onEvent, onError, onClosed, cancellationToken); - } - - /// - /// Creates a namespaceProperty-scoped Watch on the resource. - /// - /// the object type - /// the namespaceProperty - /// action on event - /// action on error - /// action on closed - /// the token - /// the watchable - public Watcher Watch(string namespaceProperty, Action onEvent, Action onError = default, Action onClosed = default, - CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return Watch(namespaceProperty, new ListOptions(), onEvent, onError, onClosed, cancellationToken); - } - - // TODO(yue9944882): watch one resource? - - /// - /// Get kubernetes object. - /// - /// the object type - /// the name - /// the get options - /// the token - /// the kubernetes object - public async Task GetAsync(string name, GetOptions getOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - var resp = await _client.CustomObjects.GetClusterCustomObjectWithHttpMessagesAsync(group: _apiGroup, plural: _resourcePlural, version: _apiVersion, name: name, cancellationToken: cancellationToken) - .ConfigureAwait(false); - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Get kubernetes object. - /// - /// the object type - /// the namespaceProperty - /// the name - /// the get options - /// the token - /// the kubernetes object - public async Task GetAsync(string namespaceProperty, string name, GetOptions getOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - if (string.IsNullOrEmpty(namespaceProperty)) - { - throw new ArgumentNullException(nameof(namespaceProperty)); - } - - var resp = await _client.CustomObjects.GetNamespacedCustomObjectWithHttpMessagesAsync(group: _apiGroup, plural: _resourcePlural, version: _apiVersion, name: name, namespaceParameter: namespaceProperty, - cancellationToken: cancellationToken).ConfigureAwait(false); - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// List kubernetes object. - /// - /// the object type - /// the list options - /// the token - /// the kubernetes object - public async Task ListAsync(ListOptions listOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (listOptions == null) - { - throw new ArgumentNullException(nameof(listOptions)); - } - - var resp = await _client.CustomObjects.ListClusterCustomObjectWithHttpMessagesAsync(group: _apiGroup, plural: _resourcePlural, version: _apiVersion, resourceVersion: listOptions.ResourceVersion, - continueParameter: listOptions.Continue, fieldSelector: listOptions.FieldSelector, labelSelector: listOptions.LabelSelector, limit: listOptions.Limit, - timeoutSeconds: listOptions.TimeoutSeconds, cancellationToken: cancellationToken).ConfigureAwait(false); - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// List kubernetes object. - /// - /// the object type - /// the namespaceProperty - /// the list options - /// the token - /// the kubernetes object - public async Task ListAsync(string namespaceProperty, ListOptions listOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (listOptions == null) - { - throw new ArgumentNullException(nameof(listOptions)); - } - - if (string.IsNullOrEmpty(namespaceProperty)) - { - throw new ArgumentNullException(nameof(namespaceProperty)); - } - - var resp = await _client.CustomObjects.ListNamespacedCustomObjectWithHttpMessagesAsync(group: _apiGroup, plural: _resourcePlural, version: _apiVersion, resourceVersion: listOptions.ResourceVersion, - continueParameter: listOptions.Continue, fieldSelector: listOptions.FieldSelector, labelSelector: listOptions.LabelSelector, limit: listOptions.Limit, - timeoutSeconds: listOptions.TimeoutSeconds, namespaceParameter: namespaceProperty, cancellationToken: cancellationToken).ConfigureAwait(false); - - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Create kubernetes object. - /// - /// the object type - /// the object - /// the create options - /// the token - /// the kubernetes object - public async Task CreateAsync(T obj, CreateOptions createOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (createOptions == null) - { - throw new ArgumentNullException(nameof(createOptions)); - } - - V1ObjectMeta objectMeta = obj.Metadata; - - var isNamespaced = !string.IsNullOrEmpty(objectMeta.NamespaceProperty); - if (isNamespaced) - { - return await CreateAsync(objectMeta.NamespaceProperty, obj, createOptions, cancellationToken).ConfigureAwait(false); - } - - var resp = await _client.CustomObjects.CreateClusterCustomObjectWithHttpMessagesAsync(body: obj, group: _apiGroup, plural: _resourcePlural, version: _apiVersion, dryRun: createOptions.DryRun, - fieldManager: createOptions.FieldManager, cancellationToken: cancellationToken).ConfigureAwait(false); - - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Create namespaced kubernetes object. - /// - /// the object type - /// the namespace - /// the object - /// the create options - /// the token - /// the kubernetes object - public async Task CreateAsync(string namespaceProperty, T obj, CreateOptions createOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (createOptions == null) - { - throw new ArgumentNullException(nameof(createOptions)); - } - - var resp = await _client.CustomObjects.CreateNamespacedCustomObjectWithHttpMessagesAsync(body: obj, group: _apiGroup, plural: _resourcePlural, version: _apiVersion, - namespaceParameter: namespaceProperty, dryRun: createOptions.DryRun, fieldManager: createOptions.FieldManager, cancellationToken: cancellationToken).ConfigureAwait(false); - - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Update kubernetes object. - /// - /// the object type - /// the object - /// the update options - /// the token - /// the kubernetes object - public async Task UpdateAsync(T obj, UpdateOptions updateOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (updateOptions == null) - { - throw new ArgumentNullException(nameof(updateOptions)); - } - - V1ObjectMeta objectMeta = obj.Metadata; - - var isNamespaced = !string.IsNullOrEmpty(objectMeta.NamespaceProperty); - HttpOperationResponse resp; - if (isNamespaced) - { - resp = await _client.CustomObjects.ReplaceNamespacedCustomObjectWithHttpMessagesAsync(body: obj, name: objectMeta.Name, group: _apiGroup, plural: _resourcePlural, version: _apiVersion, - namespaceParameter: objectMeta.NamespaceProperty, dryRun: updateOptions.DryRun, fieldManager: updateOptions.FieldManager, cancellationToken: cancellationToken) - .ConfigureAwait(false); - } - else - { - resp = await _client.CustomObjects.ReplaceClusterCustomObjectWithHttpMessagesAsync(body: obj, name: objectMeta.Name, group: _apiGroup ?? obj.ApiGroup(), plural: _resourcePlural, - version: _apiVersion, dryRun: updateOptions.DryRun, fieldManager: updateOptions.FieldManager, cancellationToken: cancellationToken).ConfigureAwait(false); - } - - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Create kubernetes object, if the namespaceProperty in the object is present, it will send a - /// namespaceProperty-scoped requests, vice versa. - /// - /// the object type - /// the object - /// function to extract the status from the object - /// the token - /// the kubernetes object - public Task UpdateStatusAsync(T obj, Func status, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - return UpdateStatusAsync(obj, status, new UpdateOptions(), cancellationToken); - } - - /// - /// Update status of kubernetes object. - /// - /// the object type - /// the object - /// function to extract the status from the object - /// the update options - /// the token - /// the kubernetes object - public async Task UpdateStatusAsync(T obj, Func status, UpdateOptions updateOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (updateOptions == null) - { - throw new ArgumentNullException(nameof(updateOptions)); - } - - V1ObjectMeta objectMeta = obj.Metadata; - HttpOperationResponse resp; - var isNamespaced = !string.IsNullOrEmpty(objectMeta.NamespaceProperty); - if (isNamespaced) - { - resp = await _client.CustomObjects.PatchNamespacedCustomObjectStatusWithHttpMessagesAsync(body: obj, group: _apiGroup, version: _apiVersion, namespaceParameter: objectMeta.NamespaceProperty, - plural: _resourcePlural, name: objectMeta.Name, dryRun: updateOptions.DryRun, fieldManager: updateOptions.FieldManager, force: updateOptions.Force, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - else - { - resp = await _client.CustomObjects.PatchClusterCustomObjectStatusWithHttpMessagesAsync(body: obj, group: _apiGroup, version: _apiVersion, plural: _resourcePlural, name: objectMeta.Name, - dryRun: updateOptions.DryRun, fieldManager: updateOptions.FieldManager, force: updateOptions.Force, cancellationToken: cancellationToken).ConfigureAwait(false); - } - - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Patch kubernetes object. - /// - /// the object type - /// the name - /// the object - /// the patch options - /// the token - /// the kubernetes object - public async Task PatchAsync(string name, object obj, PatchOptions patchOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (patchOptions == null) - { - throw new ArgumentNullException(nameof(patchOptions)); - } - - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - var resp = await _client.CustomObjects.PatchClusterCustomObjectWithHttpMessagesAsync(body: obj, group: _apiGroup, version: _apiVersion, plural: _resourcePlural, name: name, dryRun: patchOptions.DryRun, - fieldManager: patchOptions.FieldManager, force: patchOptions.Force, cancellationToken: cancellationToken).ConfigureAwait(false); - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Patch kubernetes object. - /// - /// the object type - /// the namespaceProperty - /// the name - /// the object - /// the patch options - /// the token - /// the kubernetes object - public async Task PatchAsync(string namespaceProperty, string name, object obj, PatchOptions patchOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (string.IsNullOrEmpty(namespaceProperty)) - { - throw new ArgumentNullException(nameof(namespaceProperty)); - } - - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (patchOptions == null) - { - throw new ArgumentNullException(nameof(patchOptions)); - } - - var resp = await _client.CustomObjects.PatchNamespacedCustomObjectWithHttpMessagesAsync(body: obj, group: _apiGroup, version: _apiVersion, namespaceParameter: namespaceProperty, plural: _resourcePlural, - name: name, dryRun: patchOptions.DryRun, fieldManager: patchOptions.FieldManager, force: patchOptions.Force, cancellationToken: cancellationToken).ConfigureAwait(false); - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Delete kubernetes object. - /// - /// the object type - /// the name - /// the delete options - /// the token - /// the kubernetes object - public async Task DeleteAsync(string name, V1DeleteOptions deleteOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - var resp = await _client.CustomObjects.DeleteClusterCustomObjectWithHttpMessagesAsync( - group: _apiGroup, version: _apiVersion, plural: _resourcePlural, name: name, body: deleteOptions, cancellationToken: cancellationToken).ConfigureAwait(false); - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Delete kubernetes object. - /// - /// the object type - /// the namespaceProperty - /// the name - /// the delete options - /// the token - /// the kubernetes object - public async Task DeleteAsync(string namespaceProperty, string name, V1DeleteOptions deleteOptions, CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (string.IsNullOrEmpty(namespaceProperty)) - { - throw new ArgumentNullException(nameof(namespaceProperty)); - } - - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(nameof(name)); - } - - var resp = await _client.CustomObjects.DeleteNamespacedCustomObjectWithHttpMessagesAsync(group: _apiGroup, version: _apiVersion, namespaceParameter: namespaceProperty, plural: _resourcePlural, - name: name, body: deleteOptions, cancellationToken: cancellationToken).ConfigureAwait(false); - return KubernetesJson.Deserialize(resp.Body.ToString()); - } - - /// - /// Watch watchable. - /// - /// the list options - /// action on event - /// action on error - /// action on closed - /// the token - /// the object type - /// the watchable - public Watcher Watch(ListOptions listOptions, Action onEvent, Action onError = default, Action onClosed = default, - CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (listOptions == null) - { - throw new ArgumentNullException(nameof(listOptions)); - } - - var resp = _client.CustomObjects.ListClusterCustomObjectWithHttpMessagesAsync(group: _apiGroup, version: _apiVersion, plural: _resourcePlural, continueParameter: listOptions.Continue, - fieldSelector: listOptions.FieldSelector, labelSelector: listOptions.LabelSelector, limit: listOptions.Limit, resourceVersion: listOptions.ResourceVersion, - timeoutSeconds: listOptions.TimeoutSeconds, watch: true, cancellationToken: cancellationToken); - - return resp.Watch(onEvent, onError, onClosed); - } - - /// - /// Watch watchable. - /// - /// the namespaceProperty - /// the list options - /// action on event - /// action on error - /// action on closed - /// the token - /// the object type - /// the watchable - public Watcher Watch(string namespaceProperty, ListOptions listOptions, Action onEvent, Action onError = default, Action onClosed = default, - CancellationToken cancellationToken = default) - where T : class, IKubernetesObject - { - if (listOptions == null) - { - throw new ArgumentNullException(nameof(listOptions)); - } - - if (string.IsNullOrEmpty(namespaceProperty)) - { - throw new ArgumentNullException(nameof(namespaceProperty)); - } - - var resp = _client.CustomObjects.ListNamespacedCustomObjectWithHttpMessagesAsync(group: _apiGroup, version: _apiVersion, namespaceParameter: namespaceProperty, plural: _resourcePlural, - continueParameter: listOptions.Continue, fieldSelector: listOptions.FieldSelector, labelSelector: listOptions.LabelSelector, limit: listOptions.Limit, - resourceVersion: listOptions.ResourceVersion, timeoutSeconds: listOptions.TimeoutSeconds, watch: true, cancellationToken: cancellationToken); - - return resp.Watch(onEvent, onError, onClosed); - } - } -} diff --git a/src/KubernetesClient/Util/Common/Generic/KubernetesApiResponse.cs b/src/KubernetesClient/Util/Common/Generic/KubernetesApiResponse.cs deleted file mode 100644 index 086878380..000000000 --- a/src/KubernetesClient/Util/Common/Generic/KubernetesApiResponse.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Net; -using k8s.Models; - -namespace k8s.Util.Common.Generic -{ - public class KubernetesApiResponse - where TDataType : IKubernetesObject - { - public KubernetesApiResponse(TDataType @object) - { - Object = @object; - Status = null; - HttpStatusCode = HttpStatusCode.OK; // 200 - } - - public KubernetesApiResponse(V1Status status, HttpStatusCode httpStatusCode) - { - Object = default(TDataType); - Status = status; - HttpStatusCode = httpStatusCode; - } - - public TDataType Object { get; } - - public V1Status Status { get; } - - public HttpStatusCode HttpStatusCode { get; } - - public bool IsSuccess => ((int)HttpStatusCode > 199 && (int)HttpStatusCode < 300); // 400 - - /// - /// Throws api exception kubernetes api response on failure. This is the recommended approach to - /// deal with errors returned from server. - /// - /// the kubernetes api response - /// the api exception - public KubernetesApiResponse ThrowsApiException() - { - return OnFailure(new ErrorStatusHandler()); - } - - /// - /// Calling errorStatusHandler upon errors from server - /// - /// the error status handler - /// the kubernetes api response - public KubernetesApiResponse OnFailure(ErrorStatusHandler errorStatusHandler) - { - if (!IsSuccess && errorStatusHandler != null) - { - errorStatusHandler.Handle((int)HttpStatusCode, Status); - } - - return this; - } - - public class ErrorStatusHandler - { - public void Handle(int code, V1Status errorStatus) - { - throw new HttpListenerException(code, errorStatus?.Message); - } - } - } -} diff --git a/src/KubernetesClient/Util/Common/Generic/Options/CreateOptions.cs b/src/KubernetesClient/Util/Common/Generic/Options/CreateOptions.cs deleted file mode 100644 index 4f03284fa..000000000 --- a/src/KubernetesClient/Util/Common/Generic/Options/CreateOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace k8s.Util.Common.Generic.Options -{ - public class CreateOptions - { - public string DryRun { get; private set; } - - public string FieldManager { get; private set; } - - public CreateOptions(string dryRun = default, string fieldManager = default) - { - DryRun = dryRun; - FieldManager = fieldManager; - } - } -} diff --git a/src/KubernetesClient/Util/Common/Generic/Options/GetOptions.cs b/src/KubernetesClient/Util/Common/Generic/Options/GetOptions.cs deleted file mode 100644 index 7a1425f0b..000000000 --- a/src/KubernetesClient/Util/Common/Generic/Options/GetOptions.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace k8s.Util.Common.Generic.Options -{ - public class GetOptions - { - } -} diff --git a/src/KubernetesClient/Util/Common/Generic/Options/ListOptions.cs b/src/KubernetesClient/Util/Common/Generic/Options/ListOptions.cs deleted file mode 100644 index 7750ad6b9..000000000 --- a/src/KubernetesClient/Util/Common/Generic/Options/ListOptions.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace k8s.Util.Common.Generic.Options -{ - public class ListOptions - { - public int? TimeoutSeconds { get; private set; } - - public int Limit { get; private set; } - - public string FieldSelector { get; private set; } - - public string LabelSelector { get; private set; } - - public string ResourceVersion { get; private set; } - - public string Continue { get; private set; } - - public ListOptions(int? timeoutSeconds = default, int limit = default, string fieldSelector = default, string labelSelector = default, string resourceVersion = default, - string @continue = default) - { - TimeoutSeconds = timeoutSeconds; - Limit = limit; - FieldSelector = fieldSelector; - LabelSelector = labelSelector; - ResourceVersion = resourceVersion; - Continue = @continue; - } - } -} diff --git a/src/KubernetesClient/Util/Common/Generic/Options/PatchOptions.cs b/src/KubernetesClient/Util/Common/Generic/Options/PatchOptions.cs deleted file mode 100644 index ed81e1d51..000000000 --- a/src/KubernetesClient/Util/Common/Generic/Options/PatchOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace k8s.Util.Common.Generic.Options -{ - public class PatchOptions - { - public string DryRun { get; private set; } - - public bool Force { get; private set; } - - public string FieldManager { get; private set; } - - public PatchOptions(string dryRun = default, bool force = false, string fieldManager = default) - { - DryRun = dryRun; - Force = force; - FieldManager = fieldManager; - } - } -} diff --git a/src/KubernetesClient/Util/Common/Generic/Options/UpdateOptions.cs b/src/KubernetesClient/Util/Common/Generic/Options/UpdateOptions.cs deleted file mode 100644 index 3fcedd8f1..000000000 --- a/src/KubernetesClient/Util/Common/Generic/Options/UpdateOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace k8s.Util.Common.Generic.Options -{ - public class UpdateOptions - { - public string DryRun { get; private set; } - - public bool Force { get; private set; } - - public string FieldManager { get; private set; } - - public UpdateOptions(string dryRun = default, bool force = false, string fieldManager = default) - { - DryRun = dryRun; - Force = force; - FieldManager = fieldManager; - } - } -} diff --git a/src/KubernetesClient/Util/Common/Namespaces.cs b/src/KubernetesClient/Util/Common/Namespaces.cs deleted file mode 100644 index 1bb705c34..000000000 --- a/src/KubernetesClient/Util/Common/Namespaces.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.IO; -using System.Text; - -namespace k8s.Util.Common -{ - /// - /// Namespaces provides a set of helpers for operating namespaces. - /// - public class Namespaces - { - public const string NamespaceAll = ""; - - public const string NamespaceDefault = "default"; - - public const string NamespaceKubeSystem = "kube-system"; - - public static string GetPodNamespace() - { - return File.ReadAllText(Config.ServiceAccountNamespacePath, Encoding.UTF8); - } - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/Cache.cs b/src/KubernetesClient/Util/Informer/Cache/Cache.cs deleted file mode 100644 index 2236c3df0..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/Cache.cs +++ /dev/null @@ -1,441 +0,0 @@ -using k8s.Models; -using k8s.Util.Common; - -namespace k8s.Util.Informer.Cache -{ - /// - /// Cache is a C# port of Java's Cache which is a port of k/client-go's ThreadSafeStore. It basically saves and indexes all the entries. - /// - /// The type of K8s object to save - public class Cache : IIndexer - where TApiType : class, IKubernetesObject - { - /// - /// keyFunc defines how to map index objects into indices - /// - private Func, string> _keyFunc; - - /// - /// indexers stores index functions by their names - /// - /// The indexer name(string) is a label marking the different ways it can be calculated. - /// The default label is "namespace". The default func is to look in the object's metadata and combine the - /// namespace and name values, as namespace/name. - /// - private readonly Dictionary>> _indexers = new Dictionary>>(); - - /// - /// indices stores objects' keys by their indices - /// - /// Similar to 'indexers', an indice has the same label as its corresponding indexer except it's value - /// is the result of the func. - /// if the indexer func is to calculate the namespace and name values as namespace/name, then the indice HashSet - /// holds those values. - /// - private Dictionary>> _indices = new Dictionary>>(); - - /// - /// items stores object instances - /// - /// Indices hold the HashSet of calculated keys (namespace/name) for a given resource and items map each of - /// those keys to actual K8s object that was originally returned. - private Dictionary _items = new Dictionary(); - - /// - /// object used to track locking - /// - /// methods interacting with the store need to lock to secure the thread for race conditions, - /// learn more: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement - private readonly object _lock = new object(); - - /// - /// Initializes a new instance of the class. Uses an object's namespace as the key. - /// - public Cache() - : this(Caches.NamespaceIndex, Caches.MetaNamespaceIndexFunc, Caches.DeletionHandlingMetaNamespaceKeyFunc) - { - } - - /// - /// Initializes a new instance of the class. - /// Constructor. - /// - /// the index name, an unique name representing the index - /// the index func by which we map multiple object to an index for querying - /// the key func by which we map one object to an unique key for storing - public Cache(string indexName, Func> indexFunc, Func, string> keyFunc) - { - _indexers[indexName] = indexFunc; - _keyFunc = keyFunc; - _indices[indexName] = new Dictionary>(); - } - - public void Clear() - { - lock (_lock) - { - _items?.Clear(); - _indices?.Clear(); - _indexers?.Clear(); - } - } - - /// - /// Add objects. - /// - /// the obj - public void Add(TApiType obj) - { - var key = _keyFunc(obj); - - lock (_lock) - { - var oldObj = _items.GetValueOrDefault(key); - _items[key] = obj; - UpdateIndices(oldObj, obj, key); - } - } - - /// - /// Update the object. - /// - /// the obj - public void Update(TApiType obj) - { - var key = _keyFunc(obj); - - lock (_lock) - { - var oldObj = _items.GetValueOrDefault(key); - _items[key] = obj; - UpdateIndices(oldObj, obj, key); - } - } - - /// - /// Delete the object. - /// - /// the obj - public void Delete(TApiType obj) - { - var key = _keyFunc(obj); - lock (_lock) - { - if (!_items.TryGetValue(key, out var value)) - { - return; - } - - DeleteFromIndices(value, key); - _items.Remove(key); - } - } - - /// - /// Replace the content in the cache completely. - /// - /// the list - /// optional, unused param from interface - /// list is null - public void Replace(IEnumerable list, string resourceVersion = default) - { - if (list is null) - { - throw new ArgumentNullException(nameof(list)); - } - - var newItems = new Dictionary(); - foreach (var item in list) - { - var key = _keyFunc(item); - newItems[key] = item; - } - - lock (_lock) - { - _items = newItems; - - // rebuild any index - _indices = new Dictionary>>(); - foreach (var (key, value) in _items) - { - UpdateIndices(default, value, key); - } - } - } - - /// - /// Resync. - /// - public void Resync() - { - // Do nothing by default - } - - /// - /// List keys. - /// - /// the list - public IEnumerable ListKeys() - { - return _items.Select(item => item.Key); - } - - /// - /// Get object t. - /// - /// the obj - /// the t - public TApiType Get(TApiType obj) - { - var key = _keyFunc(obj); - - lock (_lock) - { - // Todo: to make this lock striped or reader/writer (or use ConcurrentDictionary) - return _items.GetValueOrDefault(key); - } - } - - /// - /// List all objects in the cache. - /// - /// all items - public IEnumerable List() - { - lock (_lock) - { - return _items.Select(item => item.Value); - } - } - - /// - /// Get object t. - /// - /// the key - /// the get by key - public TApiType GetByKey(string key) - { - lock (_lock) - { - _items.TryGetValue(key, out var value); - return value; - } - } - - /// - /// Get objects. - /// - /// the index name - /// the obj - /// the list - /// indexers does not contain the provided index name - public IEnumerable Index(string indexName, TApiType obj) - { - if (!_indexers.ContainsKey(indexName)) - { - throw new ArgumentException($"index {indexName} doesn't exist!", nameof(indexName)); - } - - lock (_lock) - { - var indexFunc = _indexers[indexName]; - var indexKeys = indexFunc(obj); - var index = _indices.GetValueOrDefault(indexName); - if (index is null || index.Count == 0) - { - return new List(); - } - - var returnKeySet = new HashSet(); - foreach (var set in indexKeys.Select(indexKey => index.GetValueOrDefault(indexKey)).Where(set => set != null && set.Count != 0)) - { - returnKeySet.AddRange(set); - } - - var items = new List(returnKeySet.Count); - items.AddRange(returnKeySet.Select(absoluteKey => _items[absoluteKey])); - - return items; - } - } - - /// - /// Index keys list. - /// - /// the index name - /// the index key - /// the list - /// indexers does not contain the provided index name - /// indices collection does not contain the provided index name - public IEnumerable IndexKeys(string indexName, string indexKey) - { - if (!_indexers.ContainsKey(indexName)) - { - throw new ArgumentException($"index {indexName} doesn't exist!", nameof(indexName)); - } - - lock (_lock) - { - var index = _indices.GetValueOrDefault(indexName); - - if (index is null) - { - throw new KeyNotFoundException($"no value could be found for name '{indexName}'"); - } - - return index[indexKey]; - } - } - - /// - /// By index list. - /// - /// the index name - /// the index key - /// the list - /// indexers does not contain the provided index name - /// indices collection does not contain the provided index name - public IEnumerable ByIndex(string indexName, string indexKey) - { - if (!_indexers.ContainsKey(indexName)) - { - throw new ArgumentException($"index {indexName} doesn't exist!", nameof(indexName)); - } - - var index = _indices.GetValueOrDefault(indexName); - - if (index is null) - { - throw new KeyNotFoundException($"no value could be found for name '{indexName}'"); - } - - var set = index[indexKey]; - return set is null ? new List() : set.Select(key => _items[key]); - } - - /// - /// Return the indexers registered with the cache. - /// - /// registered indexers - public IDictionary>> GetIndexers() => _indexers; - - /// - /// Add additional indexers to the cache. - /// - /// indexers to add - /// newIndexers is null - /// items collection is not empty - /// conflict between keys in existing index and new indexers provided - public void AddIndexers(IDictionary>> newIndexers) - { - if (newIndexers is null) - { - throw new ArgumentNullException(nameof(newIndexers)); - } - - if (_items.Any()) - { - throw new InvalidOperationException("cannot add indexers to a non-empty cache"); - } - - var oldKeys = _indexers.Keys; - var newKeys = newIndexers.Keys; - var intersection = oldKeys.Intersect(newKeys); - - if (intersection.Any()) - { - throw new ArgumentException("indexer conflict: " + intersection); - } - - foreach (var (key, value) in newIndexers) - { - AddIndexFunc(key, value); - } - } - - /// - /// UpdateIndices modifies the objects location in the managed indexes, if this is an update, you - /// must provide an oldObj. - /// - /// UpdateIndices must be called from a function that already has a lock on the cache. - /// the old obj - /// the new obj - /// the key - private void UpdateIndices(TApiType oldObj, TApiType newObj, string key) - { - // if we got an old object, we need to remove it before we can add - // it again. - if (oldObj != null) - { - DeleteFromIndices(oldObj, key); - } - - foreach (var (indexName, indexFunc) in _indexers) - { - var indexValues = indexFunc(newObj); - if (indexValues is null || indexValues.Count == 0) - { - continue; - } - - var index = _indices.ComputeIfAbsent(indexName, _ => new Dictionary>()); - - foreach (var indexValue in indexValues) - { - HashSet indexSet = index.ComputeIfAbsent(indexValue, k => new HashSet()); - indexSet.Add(key); - - index[indexValue] = indexSet; - } - } - } - - /// - /// DeleteFromIndices removes the object from each of the managed indexes. - /// - /// It is intended to be called from a function that already has a lock on the cache. - /// the old obj - /// the key - private void DeleteFromIndices(TApiType oldObj, string key) - { - foreach (var (s, indexFunc) in _indexers) - { - var indexValues = indexFunc(oldObj); - if (indexValues is null || indexValues.Count == 0) - { - continue; - } - - var index = _indices.GetValueOrDefault(s); - if (index is null) - { - continue; - } - - foreach (var indexSet in indexValues.Select(indexValue => index[indexValue])) - { - indexSet?.Remove(key); - } - } - } - - /// - /// Add index func. - /// - /// the index name - /// the index func - public void AddIndexFunc(string indexName, Func> indexFunc) - { - _indices[indexName] = new Dictionary>(); - _indexers[indexName] = indexFunc; - } - - public Func, string> KeyFunc => _keyFunc; - - public void SetKeyFunc(Func, string> keyFunc) - { - _keyFunc = keyFunc; - } - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/Caches.cs b/src/KubernetesClient/Util/Informer/Cache/Caches.cs deleted file mode 100644 index 21339b015..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/Caches.cs +++ /dev/null @@ -1,83 +0,0 @@ -using k8s.Models; - -namespace k8s.Util.Informer.Cache -{ - /// - /// A set of helper utilities for constructing a cache. - /// - public static class Caches - { - /// - /// NamespaceIndex is the default index function for caching objects - /// - public const string NamespaceIndex = "namespace"; - - /// - /// deletionHandlingMetaNamespaceKeyFunc checks for DeletedFinalStateUnknown objects before calling - /// metaNamespaceKeyFunc. - /// - /// specific object - /// the type parameter - /// if obj is null - /// the key - public static string DeletionHandlingMetaNamespaceKeyFunc(TApiType obj) - where TApiType : class, IKubernetesObject - { - if (obj is null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (obj.GetType() == typeof(DeletedFinalStateUnknown)) - { - var deleteObj = obj as DeletedFinalStateUnknown; - return deleteObj.GetKey(); - } - - return MetaNamespaceKeyFunc(obj); - } - - /// - /// MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make keys for API - /// objects which implement V1ObjectMeta Interface. The key uses the format <namespace>/<name> - /// unless <namespace> is empty, then it's just <name>. - /// - /// specific object - /// the key - /// if obj is null - /// if metadata can't be found on obj - public static string MetaNamespaceKeyFunc(IKubernetesObject obj) - { - if (obj is null) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (!string.IsNullOrEmpty(obj.Metadata.NamespaceProperty)) - { - return obj.Metadata.NamespaceProperty + "/" + obj.Metadata.Name; - } - - return obj.Metadata.Name; - } - - /// - /// MetaNamespaceIndexFunc is a default index function that indexes based on an object's namespace. - /// - /// specific object - /// the type parameter - /// the indexed value - /// if obj is null - /// if metadata can't be found on obj - public static List MetaNamespaceIndexFunc(TApiType obj) - where TApiType : IKubernetesObject - { - if (obj is null) - { - throw new ArgumentNullException(nameof(obj)); - } - - return obj.Metadata is null ? new List() : new List() { obj.Metadata.NamespaceProperty }; - } - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/DeletedFinalStateUnknown.cs b/src/KubernetesClient/Util/Informer/Cache/DeletedFinalStateUnknown.cs deleted file mode 100644 index 7e8a99553..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/DeletedFinalStateUnknown.cs +++ /dev/null @@ -1,47 +0,0 @@ -using k8s.Models; - -namespace k8s.Util.Informer.Cache -{ - // DeletedFinalStateUnknown is placed into a DeltaFIFO in the case where - // an object was deleted but the watch deletion event was missed. In this - // case we don't know the final "resting" state of the object, so there's - // a chance the included `Obj` is stale. - public class DeletedFinalStateUnknown : IKubernetesObject - where TApi : class, IKubernetesObject - { - private readonly string _key; - private readonly TApi _obj; - - public DeletedFinalStateUnknown(string key, TApi obj) - { - _key = key; - _obj = obj; - } - - public string GetKey() => _key; - - /// - /// Gets get obj. - /// - /// the get obj - public TApi GetObj() => _obj; - - public V1ObjectMeta Metadata - { - get => _obj.Metadata; - set => _obj.Metadata = value; - } - - public string ApiVersion - { - get => _obj.ApiVersion; - set => _obj.ApiVersion = value; - } - - public string Kind - { - get => _obj.Kind; - set => _obj.Kind = value; - } - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/DeltaType.cs b/src/KubernetesClient/Util/Informer/Cache/DeltaType.cs deleted file mode 100644 index b8f10c4fa..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/DeltaType.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace k8s.Util.Informer.Cache -{ - public enum DeltaType - { - /// - /// Item added - /// - Added, - - /// - /// Item updated - /// - Updated, - - /// - /// Item deleted - /// - Deleted, - - /// - /// Item synchronized - /// - Sync, - - /// - /// Item replaced - /// - Replaced, - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/IIndexer.cs b/src/KubernetesClient/Util/Informer/Cache/IIndexer.cs deleted file mode 100644 index 76f6fae76..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/IIndexer.cs +++ /dev/null @@ -1,44 +0,0 @@ -using k8s.Models; - -namespace k8s.Util.Informer.Cache -{ - public interface IIndexer : IStore - where TApiType : class, IKubernetesObject - { - /// - /// Retrieve list of objects that match on the named indexing function. - /// - /// specific indexing function - /// . - /// matched objects - IEnumerable Index(string indexName, TApiType obj); - - /// - /// IndexKeys returns the set of keys that match on the named indexing function. - /// - /// specific indexing function - /// specific index key - /// matched keys - IEnumerable IndexKeys(string indexName, string indexKey); - - /// - /// ByIndex lists object that match on the named indexing function with the exact key. - /// - /// specific indexing function - /// specific index key - /// matched objects - IEnumerable ByIndex(string indexName, string indexKey); - - /// - /// Return the indexers registered with the store. - /// - /// registered indexers - IDictionary>> GetIndexers(); - - /// - /// Add additional indexers to the store. - /// - /// indexers to add - void AddIndexers(IDictionary>> indexers); - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/IStore.cs b/src/KubernetesClient/Util/Informer/Cache/IStore.cs deleted file mode 100644 index 68d07506f..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/IStore.cs +++ /dev/null @@ -1,69 +0,0 @@ -using k8s.Models; - -namespace k8s.Util.Informer.Cache -{ - public interface IStore - where TApiType : class, IKubernetesObject - { - /// - /// add inserts an item into the store. - /// - /// specific obj - void Add(TApiType obj); - - /// - /// update sets an item in the store to its updated state. - /// - /// specific obj - void Update(TApiType obj); - - /// - /// delete removes an item from the store. - /// - /// specific obj - void Delete(TApiType obj); - - /// - /// Replace will delete the contents of 'c', using instead the given list. - /// - /// list of objects - /// specific resource version - void Replace(IEnumerable list, string resourceVersion); - - /// - /// resync will send a resync event for each item. - /// - void Resync(); - - /// - /// listKeys returns a list of all the keys of the object currently in the store. - /// - /// list of all keys - IEnumerable ListKeys(); - - /// - /// get returns the requested item. - /// - /// specific obj - /// the requested item if exist - TApiType Get(TApiType obj); - - /// - /// getByKey returns the request item with specific key. - /// - /// specific key - /// the request item - TApiType GetByKey(string key); - - /// - /// list returns a list of all the items. - /// - /// list of all the items - IEnumerable List(); - - /// - /// Empty the store - /// - void Clear(); - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/Lister.cs b/src/KubernetesClient/Util/Informer/Cache/Lister.cs deleted file mode 100644 index e651f1257..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/Lister.cs +++ /dev/null @@ -1,44 +0,0 @@ -using k8s.Models; - -namespace k8s.Util.Informer.Cache -{ - /// - /// Lister interface is used to list cached items from a running informer. - /// - /// the type - public class Lister - where TApiType : class, IKubernetesObject - { - private readonly string _namespace; - private readonly string _indexName; - private readonly IIndexer _indexer; - - public Lister(IIndexer indexer, string @namespace = default, string indexName = Caches.NamespaceIndex) - { - _indexer = indexer; - _namespace = @namespace; - _indexName = indexName; - } - - public IEnumerable List() - { - return string.IsNullOrEmpty(_namespace) ? _indexer.List() : _indexer.ByIndex(_indexName, _namespace); - } - - public TApiType Get(string name) - { - var key = name; - if (!string.IsNullOrEmpty(_namespace)) - { - key = _namespace + "/" + name; - } - - return _indexer.GetByKey(key); - } - - public Lister Namespace(string @namespace) - { - return new Lister(_indexer, @namespace, Caches.NamespaceIndex); - } - } -} diff --git a/src/KubernetesClient/Util/Informer/Cache/MutablePair.cs b/src/KubernetesClient/Util/Informer/Cache/MutablePair.cs deleted file mode 100644 index f412d1001..000000000 --- a/src/KubernetesClient/Util/Informer/Cache/MutablePair.cs +++ /dev/null @@ -1,52 +0,0 @@ -namespace k8s.Util.Informer.Cache -{ - public class MutablePair - { - protected bool Equals(MutablePair other) - { - if (other is null) - { - throw new ArgumentNullException(nameof(other)); - } - - return EqualityComparer.Default.Equals(Left, other.Left) && EqualityComparer.Default.Equals(Right, other.Right); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - - if (ReferenceEquals(this, obj)) - { - return true; - } - - return obj.GetType() == this.GetType() && Equals((MutablePair)obj); - } - - public override int GetHashCode() - { - unchecked - { - return (EqualityComparer.Default.GetHashCode(Left) * 397) ^ EqualityComparer.Default.GetHashCode(Right); - } - } - - public TRight Right { get; } - - public TLeft Left { get; } - - public MutablePair() - { - } - - public MutablePair(TLeft left, TRight right) - { - Left = left; - Right = right; - } - } -} diff --git a/tests/KubernetesClient.Tests/KubernetesClient.Tests.csproj b/tests/KubernetesClient.Tests/KubernetesClient.Tests.csproj index 20c65d213..700a920a0 100644 --- a/tests/KubernetesClient.Tests/KubernetesClient.Tests.csproj +++ b/tests/KubernetesClient.Tests/KubernetesClient.Tests.csproj @@ -38,13 +38,6 @@ - - - - - - - diff --git a/tests/KubernetesClient.Tests/Util/Common/Generic/GenericKubernetesApiTest.cs b/tests/KubernetesClient.Tests/Util/Common/Generic/GenericKubernetesApiTest.cs deleted file mode 100644 index 3475de856..000000000 --- a/tests/KubernetesClient.Tests/Util/Common/Generic/GenericKubernetesApiTest.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using FluentAssertions; -using k8s.Models; -using k8s.Tests.Mock; -using k8s.Util.Common; -using Xunit; -using Xunit.Abstractions; - -namespace k8s.Tests.Util.Common.Generic -{ - public class GenericKubernetesApiTest - { - private readonly ITestOutputHelper _outputHelper; - - public GenericKubernetesApiTest(ITestOutputHelper outputHelper) - { - _outputHelper = outputHelper; - } - - [Fact(DisplayName = "Create constructor success")] - public void CreateConstSuccess() - { - using var server = new MockKubeApiServer(_outputHelper); - var genericApi = Helpers.BuildGenericApi(server.Uri); - genericApi.Should().NotBeNull(); - } - - [Fact(DisplayName = "Get namespaced object success")] - public async Task GetNamespacedObject() - { - var serverOptions = new MockKubeApiServerOptions(MockKubeServerFlags.GetPod); - using var server = new MockKubeApiServer(_outputHelper, serverOptions.ShouldNext); - var podName = "nginx-1493591563-xb2v4"; - var genericApi = Helpers.BuildGenericApi(server.Uri); - - var resp = await genericApi.GetAsync(Namespaces.NamespaceDefault, podName).ConfigureAwait(false); - - resp.Should().NotBeNull(); - resp.Metadata.Name.Should().Be(podName); - resp.Metadata.NamespaceProperty.Should().Be(Namespaces.NamespaceDefault); - } - - [Fact(DisplayName = "List namespaced object success")] - public async Task ListNamespacedObject() - { - var serverOptions = new MockKubeApiServerOptions(MockKubeServerFlags.ListPods); - using var server = new MockKubeApiServer(_outputHelper, serverOptions.ShouldNext); - var genericApi = Helpers.BuildGenericApi(server.Uri); - - var resp = await genericApi.ListAsync(Namespaces.NamespaceDefault).ConfigureAwait(false); - - resp.Should().NotBeNull(); - resp.Items.Should().NotBeNull(); - } - - [Fact(DisplayName = "Patch namespaced object success")] - public async Task PatchNamespacedObject() - { - using var server = new MockKubeApiServer(_outputHelper); - var podName = "nginx-1493591563-xb2v4"; - var genericApi = Helpers.BuildGenericApi(server.Uri); - - var resp = await genericApi.PatchAsync(Namespaces.NamespaceDefault, podName).ConfigureAwait(false); - - resp.Should().NotBeNull(); - } - - [Fact(DisplayName = "Update object success")] - public async Task UpdateObject() - { - using var server = new MockKubeApiServer(_outputHelper); - var pod = Helpers.CreatePods(1).First(); - var genericApi = Helpers.BuildGenericApi(server.Uri); - - var resp = await genericApi.UpdateAsync(pod).ConfigureAwait(false); - - resp.Should().NotBeNull(); - } - - [Fact(DisplayName = "Delete namespaced object success")] - public async Task DeleteNamespacedObject() - { - using var server = new MockKubeApiServer(_outputHelper); - var podName = "nginx-1493591563-xb2v4"; - var genericApi = Helpers.BuildGenericApi(server.Uri); - - var resp = await genericApi.DeleteAsync(Namespaces.NamespaceDefault, podName).ConfigureAwait(false); - - resp.Should().NotBeNull(); - } - - [Fact(DisplayName = "Watch namespaced object success")] - public void WatchNamespacedObject() - { - using var cts = new CancellationTokenSource(); - var serverOptions = new MockKubeApiServerOptions(MockKubeServerFlags.ModifiedPod); - using var server = new MockKubeApiServer(_outputHelper, serverOptions.ShouldNext); - var genericApi = Helpers.BuildGenericApi(server.Uri); - - using var resp = genericApi.Watch(Namespaces.NamespaceDefault, (actionType, pod) => { }, exception => { }, () => { }, cts.Token); - - resp.Should().NotBeNull(); - cts.CancelAfter(1000); - serverOptions.ServerShutdown?.Set(); - } - } -} diff --git a/tests/KubernetesClient.Tests/Util/Helpers.cs b/tests/KubernetesClient.Tests/Util/Helpers.cs deleted file mode 100644 index 87a972131..000000000 --- a/tests/KubernetesClient.Tests/Util/Helpers.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using k8s.Models; -using k8s.Util.Common.Generic; - -namespace k8s.Tests.Util -{ - internal static class Helpers - { - public static IEnumerable CreatePods(int cnt) - { - var pods = new List(); - for (var i = 0; i < cnt; i++) - { - pods.Add(new V1Pod() - { - ApiVersion = "Pod/V1", - Kind = "Pod", - Metadata = new V1ObjectMeta() - { - Name = Guid.NewGuid().ToString(), - NamespaceProperty = "the-namespace", - ResourceVersion = DateTime.Now.Ticks.ToString(), - }, - }); - } - - return pods; - } - - public static V1PodList CreatePodList(int cnt) - { - return new V1PodList() - { - ApiVersion = "Pod/V1", - Kind = "Pod", - Metadata = new V1ListMeta() - { - ResourceVersion = DateTime.Now.Ticks.ToString(), - }, - Items = CreatePods(cnt).ToList(), - }; - } - - public static Kubernetes BuildApiClient(Uri hostAddress) - { - return new Kubernetes(new KubernetesClientConfiguration { Host = hostAddress.ToString() }) - { - HttpClient = - { - Timeout = Timeout.InfiniteTimeSpan, - }, - }; - } - - public static GenericKubernetesApi BuildGenericApi(Uri hostAddress) - { - return new GenericKubernetesApi( - apiGroup: "pod", - apiVersion: "v1", - resourcePlural: "pods", - apiClient: BuildApiClient(hostAddress)); - } - } -} diff --git a/tests/KubernetesClient.Tests/Util/Informer/Cache/CacheTest.cs b/tests/KubernetesClient.Tests/Util/Informer/Cache/CacheTest.cs deleted file mode 100644 index d97d647e3..000000000 --- a/tests/KubernetesClient.Tests/Util/Informer/Cache/CacheTest.cs +++ /dev/null @@ -1,335 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using FluentAssertions; -using k8s.Models; -using k8s.Util.Informer.Cache; -using Xunit; - -namespace k8s.Tests.Util.Informer.Cache -{ - public class CacheTest - { - [Fact(DisplayName = "Create default cache success")] - public void CreateCacheSuccess() - { - var cache = new Cache(); - cache.Should().NotBeNull(); - cache.GetIndexers().ContainsKey(Caches.NamespaceIndex).Should().BeTrue(); - } - - [Fact(DisplayName = "Add cache item success")] - public void AddCacheItemSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - - cache.Add(aPod); - - cache.Get(aPod).Equals(aPod).Should().BeTrue(); - } - - [Fact(DisplayName = "Update cache item success")] - public void UpdateCacheItemSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - - var cache = new Cache(); - - cache.Add(aPod); - aPod.Kind = "another-kind"; - cache.Update(aPod); - - cache.Get(aPod).Kind.Equals(aPod.Kind).Should().BeTrue(); - } - - [Fact(DisplayName = "Delete cache item success")] - public void DeleteCacheItemSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - - var cache = new Cache(); - - cache.Add(aPod); - cache.Delete(aPod); - - // Todo: check indices for removed item - cache.Get(aPod).Should().BeNull(); - } - - [Fact(DisplayName = "Replace cache items success")] - public void ReplaceCacheItemsSuccess() - { - var pods = Helpers.CreatePods(3); - var aPod = pods.First(); - var anotherPod = pods.Skip(1).First(); - var yetAnotherPod = pods.Skip(2).First(); - - var cache = new Cache(); - - cache.Add(aPod); - cache.Replace(new[] { anotherPod, yetAnotherPod }); - - // Todo: check indices for replaced items - cache.Get(anotherPod).Should().NotBeNull(); - cache.Get(yetAnotherPod).Should().NotBeNull(); - } - - [Fact(DisplayName = "List item keys success")] - public void ListItemKeysSuccess() - { - var pods = Helpers.CreatePods(3); - var aPod = pods.First(); - var anotherPod = pods.Skip(1).First(); - var cache = new Cache(); - - cache.Add(aPod); - cache.Add(anotherPod); - - var keys = cache.ListKeys(); - - keys.Should().Contain($"{aPod.Metadata.NamespaceProperty}/{aPod.Metadata.Name}"); - keys.Should().Contain($"{anotherPod.Metadata.NamespaceProperty}/{anotherPod.Metadata.Name}"); - } - - [Fact(DisplayName = "Get item doesn't exist")] - public void GetItemNotExist() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - - var item = cache.Get(aPod); - item.Should().BeNull(); - } - - [Fact(DisplayName = "Get item success")] - public void GetItemSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - - cache.Add(aPod); - var item = cache.Get(aPod); - item.Equals(aPod).Should().BeTrue(); - } - - [Fact(DisplayName = "List items success")] - public void ListItemSuccess() - { - var pods = Helpers.CreatePods(3); - var aPod = pods.First(); - var anotherPod = pods.Skip(1).First(); - var yetAnotherPod = pods.Skip(2).First(); - - var cache = new Cache(); - - cache.Add(aPod); - cache.Add(anotherPod); - cache.Add(yetAnotherPod); - - var items = cache.List(); - items.Should().HaveCount(3); - items.Should().Contain(aPod); - items.Should().Contain(anotherPod); - items.Should().Contain(yetAnotherPod); - } - - [Fact(DisplayName = "Get item by key success")] - public void GetItemByKeySuccess() - { - var pod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - - cache.Add(pod); - var item = cache.GetByKey($"{pod.Metadata.NamespaceProperty}/{pod.Metadata.Name}"); - item.Should().NotBeNull(); - } - - [Fact(DisplayName = "Index items no index")] - public void IndexItemsNoIndex() - { - var pod = Helpers.CreatePods(1).First(); - - var cache = new Cache(); - - cache.Add(pod); - - Assert.Throws(() => { cache.Index("asdf", pod); }); - } - - [Fact(DisplayName = "Index items success")] - public void IndexItemsSuccess() - { - var pod = Helpers.CreatePods(1).First(); - - var cache = new Cache(); - - cache.Add(pod); - - var items = cache.Index("namespace", pod); - - items.Should().Contain(pod); - } - - [Fact(DisplayName = "Get index keys no index")] - public void GetIndexKeysNoIndex() - { - var cache = new Cache(); - - Assert.Throws(() => { cache.IndexKeys("a", "b"); }); - } - - [Fact(DisplayName = "Get index keys no indice item")] - public void GetIndexKeysNoIndiceItem() - { - var cache = new Cache(); - - Assert.Throws(() => { cache.IndexKeys("namespace", "b"); }); - } - - [Fact(DisplayName = "Get index keys success")] - public void GetIndexKeysSuccess() - { - var pod = Helpers.CreatePods(1).First(); - - var cache = new Cache(); - - cache.Add(pod); - var keys = cache.IndexKeys("namespace", pod.Metadata.NamespaceProperty); - - keys.Should().NotBeNull(); - keys.Should().Contain(Caches.MetaNamespaceKeyFunc(pod)); - } - - [Fact(DisplayName = "List by index no index")] - public void ListByIndexNoIndex() - { - var cache = new Cache(); - - Assert.Throws(() => { cache.ByIndex("a", "b"); }); - } - - [Fact(DisplayName = "List by index no indice item")] - public void ListByIndexNoIndiceItem() - { - var cache = new Cache(); - - Assert.Throws(() => { cache.ByIndex("namespace", "b"); }); - } - - [Fact(DisplayName = "List by index success")] - public void ListByIndexSuccess() - { - var pod = Helpers.CreatePods(1).First(); - - var cache = new Cache(); - - cache.Add(pod); - var items = cache.ByIndex("namespace", pod.Metadata.NamespaceProperty); - - items.Should().Contain(pod); - } - - /* Add Indexers */ - [Fact(DisplayName = "Add null indexers")] - public void AddNullIndexers() - { - var cache = new Cache(); - Assert.Throws(() => { cache.AddIndexers(null); }); - } - - [Fact(DisplayName = "Add indexers with conflict")] - public void AddIndexersConflict() - { - var cache = new Cache(); - Dictionary>> initialIndexers = new Dictionary>>() - { - { "1", pod => new List() }, - { "2", pod => new List() }, - }; - Dictionary>> conflictIndexers = new Dictionary>>() - { - { "1", pod => new List() }, - }; - - cache.AddIndexers(initialIndexers); - Assert.Throws(() => { cache.AddIndexers(conflictIndexers); }); - } - - [Fact(DisplayName = "Add indexers success")] - public void AddIndexersSuccess() - { - var cache = new Cache(); - Dictionary>> indexers = new Dictionary>>() - { - { "2", pod => new List() { pod.Name() } }, - { "3", pod => new List() { pod.Name() } }, - }; - - cache.AddIndexers(indexers); - - var savedIndexers = cache.GetIndexers(); - savedIndexers.Should().HaveCount(indexers.Count + 1); // blank cache constructor will add a default index - savedIndexers.Should().Contain(indexers); - - // Todo: check indicies collection for new indexname keys - } - - /* Add Index Function */ - [Fact(DisplayName = "Add index function success")] - public void AddIndexFuncSuccess() - { - var cache = new Cache(); - cache.AddIndexFunc("1", pod => new List() { pod.Name() }); - - var savedIndexers = cache.GetIndexers(); - savedIndexers.Should().HaveCount(2); - - // Todo: check indicies collection for new indexname keys - } - - /* Get Key Function */ - [Fact(DisplayName = "Get default key function success")] - public void GetDefaultKeyFuncSuccess() - { - var pod = new V1Pod() - { - Metadata = new V1ObjectMeta() - { - Name = "a-name", - NamespaceProperty = "the-namespace", - }, - }; - var cache = new Cache(); - var defaultReturnValue = Caches.DeletionHandlingMetaNamespaceKeyFunc(pod); - - var funcReturnValue = cache.KeyFunc(pod); - - Assert.True(defaultReturnValue.Equals(funcReturnValue)); - } - - /* Set Key Function */ - [Fact(DisplayName = "Set key function success")] - public void SetKeyFuncSuccess() - { - var aPod = new V1Pod() - { - Kind = "some-kind", - Metadata = new V1ObjectMeta() - { - Name = "a-name", - NamespaceProperty = "the-namespace", - }, - }; - var cache = new Cache(); - var newFunc = new Func, string>((pod) => pod.Kind); - var defaultReturnValue = newFunc(aPod); - - cache.SetKeyFunc(newFunc); - - var funcReturnValue = cache.KeyFunc(aPod); - - Assert.True(defaultReturnValue.Equals(funcReturnValue)); - } - } -} diff --git a/tests/KubernetesClient.Tests/Util/Informer/Cache/CachesTest.cs b/tests/KubernetesClient.Tests/Util/Informer/Cache/CachesTest.cs deleted file mode 100644 index 312a75b1b..000000000 --- a/tests/KubernetesClient.Tests/Util/Informer/Cache/CachesTest.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Linq; -using FluentAssertions; -using k8s.Models; -using Xunit; -using k8s.Util.Informer.Cache; - -namespace k8s.Tests.Util.Informer.Cache -{ - public class CachesTest - { - [Fact(DisplayName = "Check for default DeletedFinalStateUnknown")] - public void CheckDefaultDeletedFinalStateUnknown() - { - var aPod = Helpers.CreatePods(1).First(); - Caches.DeletionHandlingMetaNamespaceKeyFunc(aPod).Should().Be($"{aPod.Metadata.NamespaceProperty}/{aPod.Metadata.Name}"); - } - - [Fact(DisplayName = "Check for obj DeletedFinalStateUnknown")] - public void CheckObjDeletedFinalStateUnknown() - { - var aPod = Helpers.CreatePods(1).First(); - var key = "a-key"; - var deletedPod = new DeletedFinalStateUnknown(key, aPod); - - var returnKey = Caches.DeletionHandlingMetaNamespaceKeyFunc(deletedPod); - - // returnKey.Should().Be(key); - } - - [Fact(DisplayName = "Get default namespace key null")] - public void GetDefaultNamespaceKeyNull() - { - Assert.Throws(() => { Caches.MetaNamespaceKeyFunc(null); }); - } - - [Fact(DisplayName = "Get default namespace key success")] - public void GetDefaultNamespaceKeySuccess() - { - var aPod = Helpers.CreatePods(1).First(); - Caches.MetaNamespaceKeyFunc(aPod).Should().Be($"{aPod.Metadata.NamespaceProperty}/{aPod.Metadata.Name}"); - } - - [Fact(DisplayName = "Get default namespace index null")] - public void GetDefaultNamespaceIndexNull() - { - Assert.Throws(() => { Caches.MetaNamespaceIndexFunc(null); }); - } - - [Fact(DisplayName = "Get default namespace index success")] - public void GetDefaultNamespaceIndexSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var indexes = Caches.MetaNamespaceIndexFunc(aPod); - - indexes.Should().NotBeNull(); - indexes.Should().Contain(aPod.Metadata.NamespaceProperty); - } - } -} diff --git a/tests/KubernetesClient.Tests/Util/Informer/Cache/ListerTest.cs b/tests/KubernetesClient.Tests/Util/Informer/Cache/ListerTest.cs deleted file mode 100644 index 6a6003a03..000000000 --- a/tests/KubernetesClient.Tests/Util/Informer/Cache/ListerTest.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Linq; -using FluentAssertions; -using k8s.Models; -using k8s.Util.Informer.Cache; -using Xunit; - -namespace k8s.Tests.Util.Informer.Cache -{ - public class ListerTest - { - [Fact(DisplayName = "Create default lister success")] - public void CreateListerDefaultsSuccess() - { - var cache = new Cache(); - var lister = new Lister(cache); - - lister.Should().NotBeNull(); - } - - [Fact(DisplayName = "List with null namespace success")] - public void ListNullNamespaceSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - var lister = new Lister(cache); - - cache.Add(aPod); - var pods = lister.List(); - - pods.Should().HaveCount(1); - pods.Should().Contain(aPod); - // Can't 'Get' the pod due to no namespace specified in Lister constructor - } - - [Fact(DisplayName = "List with custom namespace success")] - public void ListCustomNamespaceSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - var lister = new Lister(cache, aPod.Metadata.NamespaceProperty); - - cache.Add(aPod); - var pods = lister.List(); - - pods.Should().HaveCount(1); - pods.Should().Contain(aPod); - lister.Get(aPod.Metadata.Name).Should().Be(aPod); - } - - [Fact(DisplayName = "Get with null namespace success")] - public void GetNullNamespaceSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - var lister = new Lister(cache); - - cache.Add(aPod); - var pod = lister.Get(aPod.Metadata.Name); - - // it's null because the namespace was not set in Lister constructor, but the pod did have a namespace. - // So it can't build the right key name for lookup in Cache - pod.Should().BeNull(); - } - - [Fact(DisplayName = "Get with custom namespace success")] - public void GetCustomNamespaceSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - var lister = new Lister(cache, aPod.Metadata.NamespaceProperty); - - cache.Add(aPod); - var pod = lister.Get(aPod.Metadata.Name); - - pod.Should().Be(aPod); - } - - [Fact(DisplayName = "Set custom namespace success")] - public void SetCustomNamespaceSuccess() - { - var aPod = Helpers.CreatePods(1).First(); - var cache = new Cache(); - var lister = new Lister(cache); - - cache.Add(aPod); - var pod = lister.Get(aPod.Metadata.Name); - pod.Should().BeNull(); - - lister = lister.Namespace(aPod.Metadata.NamespaceProperty); - - pod = lister.Get(aPod.Metadata.Name); - pod.Should().Be(aPod); - } - } -} diff --git a/tests/KubernetesClient.Tests/Util/MockKubeApiServerOptions.cs b/tests/KubernetesClient.Tests/Util/MockKubeApiServerOptions.cs deleted file mode 100644 index 08c1971a1..000000000 --- a/tests/KubernetesClient.Tests/Util/MockKubeApiServerOptions.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using k8s.Models; -using Microsoft.AspNetCore.Http; -using Nito.AsyncEx; - -namespace k8s.Tests.Util -{ - /// - /// Flags to configure how the server will respond to requests - /// - [Flags] - public enum MockKubeServerFlags - { - /// - /// No flag - /// - None = 0, - - /// - /// Include a response with malformed json - /// - BadJson = 1, - - /// - /// Include a pod added response - /// - AddedPod = 2, - - /// - /// Include a pod delete response - /// - DeletedPod = 4, - - /// - /// Include a pod modified response - /// - ModifiedPod = 8, - - /// - /// Include a pod error response - /// - ErrorPod = 16, - - /// - /// Include a response of pod list - /// - ListPods = 32, - - /// - /// Include a reponse of get pod - /// - GetPod = 64, - - /// - /// Throw a 500 Http status code on any request - /// - Throw500 = 128, - } - - internal class MockKubeApiServerOptions - { - // paste from minikube /api/v1/namespaces/default/pods - public const string MockPodResponse = - "{\r\n \"kind\": \"PodList\",\r\n \"apiVersion\": \"v1\",\r\n \"metadata\": {\r\n \"selfLink\": \"/api/v1/namespaces/default/pods\",\r\n \"resourceVersion\": \"1762810\"\r\n },\r\n \"items\": [\r\n {\r\n \"metadata\": {\r\n \"name\": \"nginx-1493591563-xb2v4\",\r\n \"generateName\": \"nginx-1493591563-\",\r\n \"namespace\": \"default\",\r\n \"selfLink\": \"/api/v1/namespaces/default/pods/nginx-1493591563-xb2v4\",\r\n \"uid\": \"ac1abb94-9c58-11e7-aaf5-00155d744505\",\r\n \"resourceVersion\": \"1737928\",\r\n \"creationTimestamp\": \"2017-09-18T10:03:51Z\",\r\n \"labels\": {\r\n \"app\": \"nginx\",\r\n \"pod-template-hash\": \"1493591563\"\r\n },\r\n \"annotations\": {\r\n \"kubernetes.io/created-by\": \"{\\\"kind\\\":\\\"SerializedReference\\\",\\\"apiVersion\\\":\\\"v1\\\",\\\"reference\\\":{\\\"kind\\\":\\\"ReplicaSet\\\",\\\"namespace\\\":\\\"default\\\",\\\"name\\\":\\\"nginx-1493591563\\\",\\\"uid\\\":\\\"ac013b63-9c58-11e7-aaf5-00155d744505\\\",\\\"apiVersion\\\":\\\"extensions\\\",\\\"resourceVersion\\\":\\\"5306\\\"}}\\n\"\r\n },\r\n \"ownerReferences\": [\r\n {\r\n \"apiVersion\": \"extensions/v1beta1\",\r\n \"kind\": \"ReplicaSet\",\r\n \"name\": \"nginx-1493591563\",\r\n \"uid\": \"ac013b63-9c58-11e7-aaf5-00155d744505\",\r\n \"controller\": true,\r\n \"blockOwnerDeletion\": true\r\n }\r\n ]\r\n },\r\n \"spec\": {\r\n \"volumes\": [\r\n {\r\n \"name\": \"default-token-3zzcj\",\r\n \"secret\": {\r\n \"secretName\": \"default-token-3zzcj\",\r\n \"defaultMode\": 420\r\n }\r\n }\r\n ],\r\n \"containers\": [\r\n {\r\n \"name\": \"nginx\",\r\n \"image\": \"nginx\",\r\n \"resources\": {},\r\n \"volumeMounts\": [\r\n {\r\n \"name\": \"default-token-3zzcj\",\r\n \"readOnly\": true,\r\n \"mountPath\": \"/var/run/secrets/kubernetes.io/serviceaccount\"\r\n }\r\n ],\r\n \"terminationMessagePath\": \"/dev/termination-log\",\r\n \"terminationMessagePolicy\": \"File\",\r\n \"imagePullPolicy\": \"Always\"\r\n }\r\n ],\r\n \"restartPolicy\": \"Always\",\r\n \"terminationGracePeriodSeconds\": 30,\r\n \"dnsPolicy\": \"ClusterFirst\",\r\n \"serviceAccountName\": \"default\",\r\n \"serviceAccount\": \"default\",\r\n \"nodeName\": \"ubuntu\",\r\n \"securityContext\": {},\r\n \"schedulerName\": \"default-scheduler\"\r\n },\r\n \"status\": {\r\n \"phase\": \"Running\",\r\n \"conditions\": [\r\n {\r\n \"type\": \"Initialized\",\r\n \"status\": \"True\",\r\n \"lastProbeTime\": null,\r\n \"lastTransitionTime\": \"2017-09-18T10:03:51Z\"\r\n },\r\n {\r\n \"type\": \"Ready\",\r\n \"status\": \"True\",\r\n \"lastProbeTime\": null,\r\n \"lastTransitionTime\": \"2017-10-12T07:09:21Z\"\r\n },\r\n {\r\n \"type\": \"PodScheduled\",\r\n \"status\": \"True\",\r\n \"lastProbeTime\": null,\r\n \"lastTransitionTime\": \"2017-09-18T10:03:51Z\"\r\n }\r\n ],\r\n \"hostIP\": \"192.168.188.42\",\r\n \"podIP\": \"172.17.0.5\",\r\n \"startTime\": \"2017-09-18T10:03:51Z\",\r\n \"containerStatuses\": [\r\n {\r\n \"name\": \"nginx\",\r\n \"state\": {\r\n \"running\": {\r\n \"startedAt\": \"2017-10-12T07:09:20Z\"\r\n }\r\n },\r\n \"lastState\": {\r\n \"terminated\": {\r\n \"exitCode\": 0,\r\n \"reason\": \"Completed\",\r\n \"startedAt\": \"2017-10-10T21:35:51Z\",\r\n \"finishedAt\": \"2017-10-12T07:07:37Z\",\r\n \"containerID\": \"docker://94df3f3965807421ad6dc76618e00b76cb15d024919c4946f3eb46a92659c62a\"\r\n }\r\n },\r\n \"ready\": true,\r\n \"restartCount\": 7,\r\n \"image\": \"nginx:latest\",\r\n \"imageID\": \"docker-pullable://nginx@sha256:004ac1d5e791e705f12a17c80d7bb1e8f7f01aa7dca7deee6e65a03465392072\",\r\n \"containerID\": \"docker://fa11bdd48c9b7d3a6c4c3f9b6d7319743c3455ab8d00c57d59c083b319b88194\"\r\n }\r\n ],\r\n \"qosClass\": \"BestEffort\"\r\n }\r\n }\r\n ]\r\n}"; - - public AsyncManualResetEvent ServerShutdown { get; private set; } - - private readonly MockKubeServerFlags _serverFlags; - private readonly string _mockAddedEventStreamLine = BuildWatchEventStreamLine(WatchEventType.Added); - private readonly string _mockDeletedStreamLine = BuildWatchEventStreamLine(WatchEventType.Deleted); - private readonly string _mockModifiedStreamLine = BuildWatchEventStreamLine(WatchEventType.Modified); - private readonly string _mockErrorStreamLine = BuildWatchEventStreamLine(WatchEventType.Error); - private const string MockBadStreamLine = "bad json"; - - public MockKubeApiServerOptions(MockKubeServerFlags? serverFlags) - { - _serverFlags = serverFlags ?? MockKubeServerFlags.None; - } - - private static string BuildWatchEventStreamLine(WatchEventType eventType) - { - var corev1PodList = KubernetesJson.Deserialize(MockPodResponse); - return KubernetesJson.Serialize(new Watcher.WatchEvent { Type = eventType, Object = corev1PodList.Items.First() }); - } - - private async Task WriteStreamLine(HttpContext httpContext, string reponseLine) - { - const string crlf = "\r\n"; - await httpContext.Response.WriteAsync(reponseLine.Replace(crlf, "")).ConfigureAwait(false); - await httpContext.Response.WriteAsync(crlf).ConfigureAwait(false); - await httpContext.Response.Body.FlushAsync().ConfigureAwait(false); - } - - public async Task ShouldNext(HttpContext httpContext) - { - var isWatch = (httpContext.Request.Query.ContainsKey("watch") && httpContext.Request.Query["watch"] == "true"); - var returnStatusCode = (_serverFlags.HasFlag(MockKubeServerFlags.Throw500) ? HttpStatusCode.InternalServerError : HttpStatusCode.OK); - - httpContext.Response.StatusCode = (int)returnStatusCode; - httpContext.Response.ContentLength = null; - - if (isWatch) - { - ServerShutdown = new AsyncManualResetEvent(); - - foreach (Enum flag in Enum.GetValues(_serverFlags.GetType())) - { - if (!_serverFlags.HasFlag(flag)) - { - continue; - } - - switch (flag) - { - case MockKubeServerFlags.AddedPod: - await WriteStreamLine(httpContext, _mockAddedEventStreamLine).ConfigureAwait(false); - break; - case MockKubeServerFlags.ErrorPod: - await WriteStreamLine(httpContext, _mockErrorStreamLine).ConfigureAwait(false); - break; - case MockKubeServerFlags.DeletedPod: - await WriteStreamLine(httpContext, _mockDeletedStreamLine).ConfigureAwait(false); - break; - case MockKubeServerFlags.ModifiedPod: - await WriteStreamLine(httpContext, _mockModifiedStreamLine).ConfigureAwait(false); - break; - case MockKubeServerFlags.BadJson: - await WriteStreamLine(httpContext, MockBadStreamLine).ConfigureAwait(false); - break; - case MockKubeServerFlags.Throw500: - return false; - } - } - - // keep server connection open - await ServerShutdown.WaitAsync().ConfigureAwait(false); - return false; - } - - foreach (Enum flag in Enum.GetValues(_serverFlags.GetType())) - { - if (!_serverFlags.HasFlag(flag)) - { - continue; - } - - switch (flag) - { - case MockKubeServerFlags.ListPods: - await WriteStreamLine(httpContext, MockPodResponse).ConfigureAwait(false); - break; - case MockKubeServerFlags.GetPod: - var corev1PodList = KubernetesJson.Deserialize(MockPodResponse); - await WriteStreamLine(httpContext, KubernetesJson.Serialize(corev1PodList.Items.First())).ConfigureAwait(false); - break; - case MockKubeServerFlags.Throw500: - return false; - } - } - - return false; - } - } -} diff --git a/tests/KubernetesClient.Util.Tests/KubernetesClient.Util.Tests.csproj b/tests/KubernetesClient.Util.Tests/KubernetesClient.Util.Tests.csproj deleted file mode 100644 index e54ad7af1..000000000 --- a/tests/KubernetesClient.Util.Tests/KubernetesClient.Util.Tests.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - net5.0 - - false - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - - - -