Skip to content

Commit 9c4c0a0

Browse files
committed
Add useful model extensions
1 parent b0e7d99 commit 9c4c0a0

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net;
5+
6+
namespace k8s.Models
7+
{
8+
public static class ModelExtensions
9+
{
10+
/// <summary>Extracts the Kubernetes API group from the <see cref="IKubernetesObject.ApiVersion"/>.</summary>
11+
public static string ApiGroup(this IKubernetesObject obj)
12+
{
13+
if(obj == null) throw new ArgumentNullException(nameof(obj));
14+
if(obj.ApiVersion == null) return null;
15+
int slash = obj.ApiVersion.IndexOf('/');
16+
return slash < 0 ? string.Empty : obj.ApiVersion.Substring(0, slash);
17+
}
18+
19+
/// <summary>Extracts the Kubernetes API version (excluding the group) from the <see cref="IKubernetesObject.ApiVersion"/>.</summary>
20+
public static string ApiGroupVersion(this IKubernetesObject obj)
21+
{
22+
if(obj == null) throw new ArgumentNullException(nameof(obj));
23+
if(obj.ApiVersion == null) return null;
24+
int slash = obj.ApiVersion.IndexOf('/');
25+
return slash < 0 ? obj.ApiVersion : obj.ApiVersion.Substring(slash+1);
26+
}
27+
28+
/// <summary>Splits the Kubernetes API version into the group and version.</summary>
29+
public static (string, string) ApiGroupAndVersion(this IKubernetesObject obj)
30+
{
31+
string group, version;
32+
obj.GetApiGroupAndVersion(out group, out version);
33+
return (group, version);
34+
}
35+
36+
/// <summary>Splits the Kubernetes API version into the group and version.</summary>
37+
public static void GetApiGroupAndVersion(this IKubernetesObject obj, out string group, out string version)
38+
{
39+
if(obj == null) throw new ArgumentNullException(nameof(obj));
40+
if(obj.ApiVersion == null)
41+
{
42+
group = version = null;
43+
}
44+
else
45+
{
46+
int slash = obj.ApiVersion.IndexOf('/');
47+
if(slash < 0) (group, version) = (string.Empty, obj.ApiVersion);
48+
else (group, version) = (obj.ApiVersion.Substring(0, slash), obj.ApiVersion.Substring(slash+1));
49+
}
50+
}
51+
52+
/// <summary>Gets the continuation token version of a Kubernetes list.</summary>
53+
public static string Continue(this IMetadata<V1ListMeta> list) => list.Metadata?.ContinueProperty;
54+
55+
/// <summary>Ensures that the <see cref="V1ListMeta"/> metadata field is set, and returns it.</summary>
56+
public static V1ListMeta EnsureMetadata(this IMetadata<V1ListMeta> obj)
57+
{
58+
if(obj.Metadata == null) obj.Metadata = new V1ListMeta();
59+
return obj.Metadata;
60+
}
61+
62+
/// <summary>Gets the resource version of a Kubernetes list.</summary>
63+
public static string ResourceVersion(this IMetadata<V1ListMeta> list) => list.Metadata?.ResourceVersion;
64+
65+
/// <summary>Adds an owner reference to the object. No attempt is made to ensure the reference is correct or fits with the
66+
/// other references.
67+
/// </summary>
68+
public static void AddOwnerReference(this IMetadata<V1ObjectMeta> obj, V1OwnerReference ownerRef)
69+
{
70+
if(obj == null) throw new ArgumentNullException(nameof(obj));
71+
if(ownerRef == null) throw new ArgumentNullException(nameof(ownerRef));
72+
if(obj.EnsureMetadata().OwnerReferences == null) obj.Metadata.OwnerReferences = new List<V1OwnerReference>();
73+
obj.Metadata.OwnerReferences.Add(ownerRef);
74+
}
75+
76+
/// <summary>Gets the annotations of a Kubernetes object.</summary>
77+
public static IDictionary<string, string> Annotations(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.Annotations;
78+
79+
/// <summary>Gets the creation time of a Kubernetes object, or null if it hasn't been created yet.</summary>
80+
public static DateTime? CreationTimestamp(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.CreationTimestamp;
81+
82+
/// <summary>Gets the deletion time of a Kubernetes object, or null if it hasn't been scheduled for deletion.</summary>
83+
public static DateTime? DeletionTimestamp(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.DeletionTimestamp;
84+
85+
/// <summary>Ensures that the <see cref="V1ObjectMeta"/> metadata field is set, and returns it.</summary>
86+
public static V1ObjectMeta EnsureMetadata(this IMetadata<V1ObjectMeta> obj)
87+
{
88+
if(obj.Metadata == null) obj.Metadata = new V1ObjectMeta();
89+
return obj.Metadata;
90+
}
91+
92+
/// <summary>Gets the index of the <see cref="V1OwnerReference"/> that matches the given object, or -1 if no such
93+
/// reference could be found.
94+
/// </summary>
95+
public static int FindOwnerRef(this IMetadata<V1ObjectMeta> obj, IKubernetesObject<V1ObjectMeta> owner)
96+
{
97+
var ownerRefs = obj.OwnerReferences();
98+
if(ownerRefs != null)
99+
{
100+
for(int i = 0; i < ownerRefs.Count; i++)
101+
{
102+
if(ownerRefs[i].Matches(owner)) return i;
103+
}
104+
}
105+
return -1;
106+
}
107+
108+
/// <summary>Gets the generation a Kubernetes object.</summary>
109+
public static long? Generation(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.Generation;
110+
111+
/// <summary>Returns the given annotation from a Kubernetes object or null if the annotation was not found.</summary>
112+
public static string GetAnnotation(this IMetadata<V1ObjectMeta> obj, string key)
113+
{
114+
if(obj == null) throw new ArgumentNullException(nameof(obj));
115+
if(key == null) throw new ArgumentNullException(nameof(key));
116+
IDictionary<string, string> annotations = obj.Annotations();
117+
return annotations != null && annotations.TryGetValue(key, out string value) ? value : null;
118+
}
119+
120+
/// <summary>Gets the <see cref="V1OwnerReference"/> for the controller of this object, or null if it couldn't be found.</summary>
121+
public static V1OwnerReference GetController(this IMetadata<V1ObjectMeta> obj) =>
122+
obj.OwnerReferences()?.FirstOrDefault(r => r.Controller.GetValueOrDefault());
123+
124+
/// <summary>Returns the given label from a Kubernetes object or null if the label was not found.</summary>
125+
public static string GetLabel(this IMetadata<V1ObjectMeta> obj, string key)
126+
{
127+
if(obj == null) throw new ArgumentNullException(nameof(obj));
128+
if(key == null) throw new ArgumentNullException(nameof(key));
129+
IDictionary<string, string> labels = obj.Labels();
130+
return labels != null && labels.TryGetValue(key, out string value) ? value : null;
131+
}
132+
133+
/// <summary>Creates a <see cref="V1ObjectReference"/> that refers to the given object.</summary>
134+
public static V1ObjectReference GetObjectReference<T>(this T obj) where T : IKubernetesObject, IMetadata<V1ObjectMeta>
135+
{
136+
if(obj == null) throw new ArgumentNullException(nameof(obj));
137+
string apiVersion = obj.ApiVersion, kind = obj.Kind; // default to using the API version and kind from the object
138+
if(string.IsNullOrEmpty(apiVersion) || string.IsNullOrEmpty(kind)) // but if either of them is missing...
139+
{
140+
object[] attrs = typeof(T).GetCustomAttributes(typeof(KubernetesEntityAttribute), true);
141+
if(attrs.Length == 0) throw new ArgumentException("Unable to determine the object's API version and Kind.");
142+
var attr = (KubernetesEntityAttribute)attrs[0];
143+
(apiVersion, kind) = (string.IsNullOrEmpty(attr.Group) ? attr.ApiVersion : attr.Group + "/" + attr.ApiVersion, attr.Kind);
144+
}
145+
return new V1ObjectReference()
146+
{
147+
ApiVersion = apiVersion, Kind = kind, Name = obj.Name(), NamespaceProperty = obj.Namespace(), Uid = obj.Uid(),
148+
ResourceVersion = obj.ResourceVersion()
149+
};
150+
}
151+
152+
/// <summary>Gets the labels of a Kubernetes object.</summary>
153+
public static IDictionary<string, string> Labels(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.Labels;
154+
155+
/// <summary>Gets the name of a Kubernetes object.</summary>
156+
public static string Name(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.Name;
157+
158+
/// <summary>Gets the namespace of a Kubernetes object.</summary>
159+
public static string Namespace(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.NamespaceProperty;
160+
161+
/// <summary>Gets the owner references of a Kubernetes object.</summary>
162+
public static IList<V1OwnerReference> OwnerReferences(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.OwnerReferences;
163+
164+
/// <summary>Gets the resource version of a Kubernetes object.</summary>
165+
public static string ResourceVersion(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.ResourceVersion;
166+
167+
/// <summary>Sets or removes an annotation on a Kubernetes object.</summary>
168+
public static void SetAnnotation(this IMetadata<V1ObjectMeta> obj, string key, string value)
169+
{
170+
if(obj == null) throw new ArgumentNullException(nameof(obj));
171+
if(key == null) throw new ArgumentNullException(nameof(key));
172+
if(value != null) obj.EnsureMetadata().EnsureAnnotations()[key] = value;
173+
else obj.Metadata?.Annotations?.Remove(key);
174+
}
175+
176+
/// <summary>Sets or removes a label on a Kubernetes object.</summary>
177+
public static void SetLabel(this IMetadata<V1ObjectMeta> obj, string key, string value)
178+
{
179+
if(obj == null) throw new ArgumentNullException(nameof(obj));
180+
if(key == null) throw new ArgumentNullException(nameof(key));
181+
if(value != null) obj.EnsureMetadata().EnsureLabels()[key] = value;
182+
else obj.Metadata?.Labels?.Remove(key);
183+
}
184+
185+
/// <summary>Gets the unique ID of a Kubernetes object.</summary>
186+
public static string Uid(this IMetadata<V1ObjectMeta> obj) => obj.Metadata?.Uid;
187+
188+
/// <summary>Ensures that the <see cref="V1ObjectMeta.Annotations"/> field is not null, and returns it.</summary>
189+
public static IDictionary<string, string> EnsureAnnotations(this V1ObjectMeta meta)
190+
{
191+
if(meta.Annotations == null) meta.Annotations = new Dictionary<string, string>();
192+
return meta.Annotations;
193+
}
194+
195+
/// <summary>Ensures that the <see cref="V1ObjectMeta.Labels"/> field is not null, and returns it.</summary>
196+
public static IDictionary<string, string> EnsureLabels(this V1ObjectMeta meta)
197+
{
198+
if(meta.Labels == null) meta.Labels = new Dictionary<string, string>();
199+
return meta.Labels;
200+
}
201+
202+
/// <summary>Gets the namespace from Kubernetes metadata.</summary>
203+
public static string Namespace(this V1ObjectMeta meta) => meta.NamespaceProperty;
204+
205+
/// <summary>Sets the namespace from Kubernetes metadata.</summary>
206+
public static void SetNamespace(this V1ObjectMeta meta, string ns) => meta.NamespaceProperty = ns;
207+
208+
/// <summary>Determines whether an object reference references the given object.</summary>
209+
public static bool Matches(this V1ObjectReference objref, IKubernetesObject<V1ObjectMeta> obj)
210+
{
211+
if(objref == null) throw new ArgumentNullException(nameof(objref));
212+
if(obj == null) throw new ArgumentNullException(nameof(obj));
213+
return objref.ApiVersion == obj.ApiVersion && objref.Kind == obj.Kind && objref.Name == obj.Name() && objref.Uid == obj.Uid() &&
214+
objref.NamespaceProperty == obj.Namespace();
215+
}
216+
217+
/// <summary>Determines whether an owner reference references the given object.</summary>
218+
public static bool Matches(this V1OwnerReference owner, IKubernetesObject<V1ObjectMeta> obj)
219+
{
220+
if(owner == null) throw new ArgumentNullException(nameof(owner));
221+
if(obj == null) throw new ArgumentNullException(nameof(obj));
222+
return owner.ApiVersion == obj.ApiVersion && owner.Kind == obj.Kind && owner.Name == obj.Name() && owner.Uid == obj.Uid();
223+
}
224+
}
225+
226+
public partial class V1Status
227+
{
228+
/// <summary>Converts a <see cref="V1Status"/> object representing an error into a short description of the error.</summary>
229+
public override string ToString()
230+
{
231+
string reason = Reason;
232+
if(string.IsNullOrEmpty(reason) && Code.GetValueOrDefault() != 0)
233+
{
234+
reason = ((HttpStatusCode)Code.Value).ToString();
235+
}
236+
return string.IsNullOrEmpty(Message) ? reason : string.IsNullOrEmpty(reason) ? Message : $"{reason} - {Message}";
237+
}
238+
}
239+
}

0 commit comments

Comments
 (0)