using System; using System.Collections.Generic; using System.Linq; using System.Net; namespace k8s.Models { /// Adds convenient extensions for Kubernetes objects. public static class ModelExtensions { /// Adds the given finalizer to a Kubernetes object if it doesn't already exist. /// Returns true if the finalizer was added and false if it already existed. public static bool AddFinalizer(this IMetadata obj, string finalizer) { if (string.IsNullOrEmpty(finalizer)) { throw new ArgumentNullException(nameof(finalizer)); } if (EnsureMetadata(obj).Finalizers == null) { obj.Metadata.Finalizers = new List(); } if (!obj.Metadata.Finalizers.Contains(finalizer)) { obj.Metadata.Finalizers.Add(finalizer); return true; } return false; } /// Extracts the Kubernetes API group from the . public static string ApiGroup(this IKubernetesObject obj) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (obj.ApiVersion != null) { int slash = obj.ApiVersion.IndexOf('/'); return slash < 0 ? string.Empty : obj.ApiVersion.Substring(0, slash); } return null; } /// Extracts the Kubernetes API version (excluding the group) from the . public static string ApiGroupVersion(this IKubernetesObject obj) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (obj.ApiVersion != null) { int slash = obj.ApiVersion.IndexOf('/'); return slash < 0 ? obj.ApiVersion : obj.ApiVersion.Substring(slash+1); } return null; } /// Splits the Kubernetes API version into the group and version. public static (string, string) ApiGroupAndVersion(this IKubernetesObject obj) { string group, version; GetApiGroupAndVersion(obj, out group, out version); return (group, version); } /// Splits the Kubernetes API version into the group and version. public static void GetApiGroupAndVersion(this IKubernetesObject obj, out string group, out string version) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (obj.ApiVersion == null) { group = version = null; } else { int slash = obj.ApiVersion.IndexOf('/'); if (slash < 0) (group, version) = (string.Empty, obj.ApiVersion); else (group, version) = (obj.ApiVersion.Substring(0, slash), obj.ApiVersion.Substring(slash+1)); } } /// Gets the continuation token version of a Kubernetes list. public static string Continue(this IMetadata list) => list.Metadata?.ContinueProperty; /// Ensures that the metadata field is set, and returns it. public static V1ListMeta EnsureMetadata(this IMetadata obj) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (obj.Metadata == null) { obj.Metadata = new V1ListMeta(); } return obj.Metadata; } /// Gets the resource version of a Kubernetes list. public static string ResourceVersion(this IMetadata list) => list.Metadata?.ResourceVersion; /// Adds an owner reference to the object. No attempt is made to ensure the reference is correct or fits with the /// other references. /// public static void AddOwnerReference(this IMetadata obj, V1OwnerReference ownerRef) { if (ownerRef == null) { throw new ArgumentNullException(nameof(ownerRef)); } if (EnsureMetadata(obj).OwnerReferences == null) { obj.Metadata.OwnerReferences = new List(); } obj.Metadata.OwnerReferences.Add(ownerRef); } /// Gets the annotations of a Kubernetes object. public static IDictionary Annotations(this IMetadata obj) => obj.Metadata?.Annotations; /// Gets the creation time of a Kubernetes object, or null if it hasn't been created yet. public static DateTime? CreationTimestamp(this IMetadata obj) => obj.Metadata?.CreationTimestamp; /// Gets the deletion time of a Kubernetes object, or null if it hasn't been scheduled for deletion. public static DateTime? DeletionTimestamp(this IMetadata obj) => obj.Metadata?.DeletionTimestamp; /// Ensures that the metadata field is set, and returns it. public static V1ObjectMeta EnsureMetadata(this IMetadata obj) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (obj.Metadata == null) { obj.Metadata = new V1ObjectMeta(); } return obj.Metadata; } /// Gets the of a Kubernetes object. public static IList Finalizers(this IMetadata obj) => obj.Metadata?.Finalizers; /// Gets the index of the that matches the given object, or -1 if no such /// reference could be found. /// public static int FindOwnerReference(this IMetadata obj, IKubernetesObject owner) => FindOwnerReference(obj, r => r.Matches(owner)); /// Gets the index of the that matches the given predicate, or -1 if no such /// reference could be found. /// public static int FindOwnerReference(this IMetadata obj, Predicate predicate) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } var ownerRefs = obj.OwnerReferences(); if (ownerRefs != null) { for (int i = 0; i < ownerRefs.Count; i++) { if (predicate(ownerRefs[i])) return i; } } return -1; } /// Gets the generation a Kubernetes object. public static long? Generation(this IMetadata obj) => obj.Metadata?.Generation; /// Returns the given annotation from a Kubernetes object or null if the annotation was not found. public static string GetAnnotation(this IMetadata obj, string key) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } IDictionary annotations = obj.Annotations(); return annotations != null && annotations.TryGetValue(key, out string value) ? value : null; } /// Gets the for the controller of this object, or null if it couldn't be found. public static V1OwnerReference GetController(this IMetadata obj) => obj.OwnerReferences()?.FirstOrDefault(r => r.Controller.GetValueOrDefault()); /// Returns the given label from a Kubernetes object or null if the label was not found. public static string GetLabel(this IMetadata obj, string key) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } IDictionary labels = obj.Labels(); return labels != null && labels.TryGetValue(key, out string value) ? value : null; } /// Gets that matches the given object, or null if no matching reference exists. public static V1OwnerReference GetOwnerReference(this IMetadata obj, IKubernetesObject owner) => GetOwnerReference(obj, r => r.Matches(owner)); /// Gets the that matches the given predicate, or null if no matching reference exists. public static V1OwnerReference GetOwnerReference(this IMetadata obj, Predicate predicate) { int index = FindOwnerReference(obj, predicate); return index >= 0 ? obj.Metadata.OwnerReferences[index] : null; } /// Determines whether the Kubernetes object has the given finalizer. public static bool HasFinalizer(this IMetadata obj, string finalizer) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (string.IsNullOrEmpty(finalizer)) { throw new ArgumentNullException(nameof(finalizer)); } return obj.Finalizers() != null && obj.Metadata.Finalizers.Contains(finalizer); } /// Determines whether one object is owned by another. public static bool IsOwnedBy(this IMetadata obj, IKubernetesObject owner) => FindOwnerReference(obj, owner) >= 0; /// Gets the labels of a Kubernetes object. public static IDictionary Labels(this IMetadata obj) => obj.Metadata?.Labels; /// Gets the name of a Kubernetes object. public static string Name(this IMetadata obj) => obj.Metadata?.Name; /// Gets the namespace of a Kubernetes object. public static string Namespace(this IMetadata obj) => obj.Metadata?.NamespaceProperty; /// Gets the owner references of a Kubernetes object. public static IList OwnerReferences(this IMetadata obj) => obj.Metadata?.OwnerReferences; /// Removes the given finalizer from a Kubernetes object if it exists. /// Returns true if the finalizer was removed and false if it didn't exist. public static bool RemoveFinalizer(this IMetadata obj, string finalizer) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (string.IsNullOrEmpty(finalizer)) { throw new ArgumentNullException(nameof(finalizer)); } return obj.Finalizers() != null && obj.Metadata.Finalizers.Remove(finalizer); } /// Removes the first that matches the given object and returns it, or returns null if no /// matching reference could be found. /// public static V1OwnerReference RemoveOwnerReference(this IMetadata obj, IKubernetesObject owner) { int index = FindOwnerReference(obj, owner); V1OwnerReference ownerRef = index >= 0 ? obj.Metadata.OwnerReferences[index] : null; if (index >= 0) { obj.Metadata.OwnerReferences.RemoveAt(index); } return ownerRef; } /// Removes all owner references that match the given predicate, and returns true if /// any were removed. /// public static bool RemoveOwnerReferences(this IMetadata obj, Predicate predicate) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } bool removed = false; IList refs = obj.Metadata?.OwnerReferences; if (refs != null) { for (int i = refs.Count-1; i >= 0; i--) { if (predicate(refs[i])) { refs.RemoveAt(i); removed = true; } } } return removed; } /// Removes all owner references that match the given object, and returns true if /// any were removed. /// public static bool RemoveOwnerReferences(this IMetadata obj, IKubernetesObject owner) => RemoveOwnerReferences(obj, r => r.Matches(owner)); /// Gets the resource version of a Kubernetes object. public static string ResourceVersion(this IMetadata obj) => obj.Metadata?.ResourceVersion; /// Sets or removes an annotation on a Kubernetes object. public static void SetAnnotation(this IMetadata obj, string key, string value) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } if (value != null) { obj.EnsureMetadata().EnsureAnnotations()[key] = value; } else { obj.Metadata?.Annotations?.Remove(key); } } /// Sets or removes a label on a Kubernetes object. public static void SetLabel(this IMetadata obj, string key, string value) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (key == null) { throw new ArgumentNullException(nameof(key)); } if (value != null) { obj.EnsureMetadata().EnsureLabels()[key] = value; } else { obj.Metadata?.Labels?.Remove(key); } } /// Gets the unique ID of a Kubernetes object. public static string Uid(this IMetadata obj) => obj.Metadata?.Uid; /// Ensures that the field is not null, and returns it. public static IDictionary EnsureAnnotations(this V1ObjectMeta meta) { if (meta == null) { throw new ArgumentNullException(nameof(meta)); } if (meta.Annotations == null) { meta.Annotations = new Dictionary(); } return meta.Annotations; } /// Ensures that the field is not null, and returns it. public static IList EnsureFinalizers(this V1ObjectMeta meta) { if (meta == null) { throw new ArgumentNullException(nameof(meta)); } if (meta.Finalizers == null) { meta.Finalizers = new List(); } return meta.Finalizers; } /// Ensures that the field is not null, and returns it. public static IDictionary EnsureLabels(this V1ObjectMeta meta) { if (meta == null) { throw new ArgumentNullException(nameof(meta)); } if (meta.Labels == null) { meta.Labels = new Dictionary(); } return meta.Labels; } /// Gets the namespace from Kubernetes metadata. public static string Namespace(this V1ObjectMeta meta) => meta.NamespaceProperty; /// Sets the namespace from Kubernetes metadata. public static void SetNamespace(this V1ObjectMeta meta, string ns) => meta.NamespaceProperty = ns; /// Determines whether an object reference references the given object. public static bool Matches(this V1ObjectReference objref, IKubernetesObject obj) { if (objref == null) { throw new ArgumentNullException(nameof(objref)); } if (obj == null) { throw new ArgumentNullException(nameof(obj)); } return objref.ApiVersion == obj.ApiVersion && objref.Kind == obj.Kind && objref.Name == obj.Name() && objref.Uid == obj.Uid() && objref.NamespaceProperty == obj.Namespace(); } /// Determines whether an owner reference references the given object. public static bool Matches(this V1OwnerReference owner, IKubernetesObject obj) { if (owner == null) { throw new ArgumentNullException(nameof(owner)); } if (obj == null) { throw new ArgumentNullException(nameof(obj)); } return owner.ApiVersion == obj.ApiVersion && owner.Kind == obj.Kind && owner.Name == obj.Name() && owner.Uid == obj.Uid(); } } public partial class V1Status { /// Converts a object into a short description of the status. public override string ToString() { string reason = Reason; if (string.IsNullOrEmpty(reason) && Code.GetValueOrDefault() != 0) { reason = ((HttpStatusCode)Code.Value).ToString(); } return string.IsNullOrEmpty(Message) ? string.IsNullOrEmpty(reason) ? Status : reason : string.IsNullOrEmpty(reason) ? Message : $"{reason} - {Message}"; } } }