/// <summary>Splits the Kubernetes API version into the group and version.</summary>
        /// <param name="obj">the kubernetes client <see cref="IKubernetesObject"/></param>
        /// <returns>api group and version from server</returns>
        public static (string, string) ApiGroupAndVersion(this IKubernetesObject obj)
        {
            string group, version;

            GetApiGroupAndVersion(obj, out group, out version);
            return(group, version);
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a <see cref="V1OwnerReference"/> which references this <see cref="IKubernetesObject{TMetadata}"/>.
        /// </summary>
        /// <param name="value">
        /// The object for which to create an owner reference.
        /// </param>
        /// <param name="blockOwnerDeletion">
        /// Gets get or sets a value indicating whether the owner cannot be deleted from the
        /// clsuter until reference is removed.
        /// </param>
        /// <param name="controller">
        /// Gets or sets a value indicating whether this reference points to the managing controller.
        /// </param>
        /// <returns>
        /// The owner reference for the object.
        /// </returns>
        public static V1OwnerReference AsOwnerReference(
            this IKubernetesObject <V1ObjectMeta> value,
            bool?blockOwnerDeletion = null,
            bool?controller         = null)
        {
            if (value.ApiVersion == null)
            {
                throw new ValidationException(ValidationRules.CannotBeNull, "value.ApiVersion");
            }

            if (value.Kind == null)
            {
                throw new ValidationException(ValidationRules.CannotBeNull, "value.Kind");
            }

            // To be kept in sync with https://github.com/kubernetes-client/csharp/blob/5be3cff425b91b1d16dd0361bf7756a0cb779d8d/src/KubernetesClient/ModelExtensions.cs#L610
            return(new V1OwnerReference()
            {
                ApiVersion = value.ApiVersion,
                Kind = value.Kind,
                Name = value.Name(),
                Uid = value.Uid(),
                BlockOwnerDeletion = blockOwnerDeletion,
                Controller = controller,
            });
        }
Esempio n. 3
0
        private static string GetObjectPath(IKubernetesObject obj, string @namespace)
        {
            string       prefix = "api", kind;
            V1ObjectMeta meta;

            if (obj is V1Pod)
            {
                kind = "pods";
                meta = ((V1Pod)obj).Metadata;
            }
            else if (obj is V1Service)
            {
                kind = "services";
                meta = ((V1Service)obj).Metadata;
            }
            else if (obj is V1Deployment)
            {
                kind   = "deployments";
                prefix = "apis/apps";
                meta   = ((V1Deployment)obj).Metadata;
            }
            else
            {
                throw new NotSupportedException("GetObjectPath only supports Pods, Services and Deployments.");
            }

            // Path structure validated against https://github.com/kubernetes-client/csharp/blob/master/src/KubernetesClient/generated/Kubernetes.Watch.cs
            return($"{prefix}/v1/watch/namespaces/{@namespace}/{kind}/{meta.Name}");
        }
 public static TResource WithOwnerReference <TResource>(
     this TResource resource,
     IKubernetesObject <V1ObjectMeta> owner)
     where TResource : IKubernetesObject <V1ObjectMeta>
 {
     resource.Metadata.EnsureOwnerReferences().Add(owner.MakeOwnerReference());
     return(resource);
 }
Esempio n. 5
0
        private async void OpenKubernetesObjectWindow(V1Namespace namespaceMetadata, object hint)
        {
            IKubernetesObject kubernetesObject = hint as IKubernetesObject;

            if (string.Equals(hint as string, "ns", StringComparison.OrdinalIgnoreCase))
            {
                kubernetesObject = namespaceMetadata;
            }

            if (kubernetesObject == null)
            {
                return;
            }

            var targetPage = default(TabPage);

            for (int i = 0; i < detailViewTabs.TabCount; i++)
            {
                if (object.ReferenceEquals(detailViewTabs.TabPages[i].Tag, kubernetesObject))
                {
                    targetPage = detailViewTabs.TabPages[i];
                    break;
                }
            }

            FetchResult content;

            try { content = await OpenKubernetesObjectInternal(namespaceMetadata, kubernetesObject); }
            catch (Exception ex)
            {
                content = new FetchResult("Error", ex.ToString());
            }

            if (targetPage == null)
            {
                targetPage = new TabPage(kubernetesObject.GetType().ToString())
                {
                    Tag  = kubernetesObject,
                    Text = content.Item1,
                };
                targetPage.Controls.Add(new RichTextBox()
                {
                    Dock              = DockStyle.Fill,
                    ReadOnly          = true,
                    Text              = content.Item2,
                    MaxLength         = Int32.MaxValue,
                    WordWrap          = false,
                    AutoWordSelection = true,
                    HideSelection     = false,
                    ScrollBars        = RichTextBoxScrollBars.ForcedBoth,
                    Font              = new Font("Consolas", 12f),
                });
                detailViewTabs.TabPages.Add(targetPage);
            }

            // TODO: Prevent focus when change visible tab
            detailViewTabs.SelectedTab = targetPage;
        }
Esempio n. 6
0
    /// <summary>
    /// Gets key values from the specified resource.
    /// </summary>
    /// <param name="resource">The resource.</param>
    /// <returns>NamespacedName.</returns>
    public static NamespacedName From(IKubernetesObject <V1ObjectMeta> resource)
    {
        if (resource is null)
        {
            throw new ArgumentNullException(nameof(resource));
        }

        return(new NamespacedName(resource.Namespace(), resource.Name()));
    }
 public static V1ObjectReference MakeObjectReference(this IKubernetesObject <V1ObjectMeta> kubernetesObject)
 => new V1ObjectReference
 {
     ApiVersion        = kubernetesObject.ApiVersion,
     Kind              = kubernetesObject.Kind,
     Name              = kubernetesObject.Metadata.Name,
     NamespaceProperty = kubernetesObject.Metadata.NamespaceProperty,
     ResourceVersion   = kubernetesObject.Metadata.ResourceVersion,
     Uid = kubernetesObject.Metadata.Uid,
 };
        public static Task RegisterFinalizer <TFinalizer, TResource>(
            this IKubernetesObject <V1ObjectMeta> resource)
            where TFinalizer : IResourceFinalizer <TResource>
            where TResource : IKubernetesObject <V1ObjectMeta>
        {
            var finalizer = DependencyInjector.Services
                            .GetServices <IResourceFinalizer <TResource> >()
                            .First(f => f.GetType() == typeof(TFinalizer));

            return(finalizer.Register((TResource)resource));
        }
Esempio n. 9
0
 private void Notification(WatchEventType eventType, IKubernetesObject <V1ObjectMeta> resource)
 {
     if (resource is TResource customResource)
     {
         OnPrimaryResourceWatchEvent(eventType, customResource);
     }
     else
     {
         OnRelatedResourceWatchEvent(eventType, resource);
     }
 }
        /// <summary>
        /// Gets key values from the specified resource.
        /// </summary>
        /// <param name="resource">The resource.</param>
        /// <returns>GroupKindNamespacedName.</returns>
        public static GroupKindNamespacedName From(IKubernetesObject <V1ObjectMeta> resource)
        {
            if (resource is null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            return(new GroupKindNamespacedName(
                       resource.ApiGroup(),
                       resource.Kind,
                       NamespacedName.From(resource)));
        }
Esempio n. 11
0
        /// <summary>Removes the first <see cref="V1OwnerReference"/> that matches the given object and returns it, or returns null if no
        /// matching reference could be found.
        /// </summary>
        public static V1OwnerReference RemoveOwnerReference(this IMetadata <V1ObjectMeta> obj,
                                                            IKubernetesObject <V1ObjectMeta> 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);
        }
Esempio n. 12
0
        /// <summary>
        /// MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make keys for API
        /// objects which implement V1ObjectMeta Interface. The key uses the format &lt;namespace&gt;/&lt;name&gt;
        /// unless &lt;namespace&gt; is empty, then it's just &lt;name&gt;.
        /// </summary>
        /// <param name="obj">specific object</param>
        /// <returns>the key</returns>
        /// <exception cref="ArgumentNullException">if obj is null</exception>
        /// <exception cref="InvalidOperationException">if metadata can't be found on obj</exception>
        public static string MetaNamespaceKeyFunc(IKubernetesObject <V1ObjectMeta> 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);
        }
Esempio n. 13
0
        /// <summary>Determines whether an owner reference references the given object.</summary>
        /// <param name="owner">the object reference<see cref="V1ObjectReference"/></param>
        /// <param name="obj">the object meta<see cref="V1ObjectMeta"/></param>
        /// <returns>true if the owner reference references the given object</returns>
        public static bool Matches(this V1OwnerReference owner, IKubernetesObject <V1ObjectMeta> 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());
        }
Esempio n. 14
0
        /// <summary>Extracts the Kubernetes API version (excluding the group) from the <see cref="IKubernetesObject.ApiVersion"/>.</summary>
        /// <param name="obj">the kubernetes client <see cref="IKubernetesObject"/></param>
        /// <returns>api group version from server</returns>
        public static string ApiGroupVersion(this IKubernetesObject obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            if (obj.ApiVersion != null)
            {
                var slash = obj.ApiVersion.IndexOf('/');
                return(slash < 0 ? obj.ApiVersion : obj.ApiVersion.Substring(slash + 1));
            }

            return(null);
        }
Esempio n. 15
0
        /// <summary>Determines whether an object reference references the given object.</summary>
        /// <param name="objref">the object reference<see cref="V1ObjectReference"/></param>
        /// <param name="obj">the object meta<see cref="V1ObjectMeta"/></param>
        /// <returns>true if the object reference references the given object.</returns>
        public static bool Matches(this V1ObjectReference objref, IKubernetesObject <V1ObjectMeta> 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());
        }
Esempio n. 16
0
        /// <summary>Splits the Kubernetes API version into the group and version.</summary>
        /// <param name="obj">the kubernetes client <see cref="IKubernetesObject"/></param>
        /// <param name="group">api group output var</param>
        /// <param name="version">api group version output var</param>
        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
            {
                var 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));
                }
            }
        }
 /// <summary>
 /// Create a custom entity definition.
 /// </summary>
 /// <param name="resource">The resource that is used as the type.</param>
 /// <returns>A <see cref="CustomEntityDefinition"/>.</returns>
 public static CustomEntityDefinition CreateResourceDefinition(
     this IKubernetesObject <V1ObjectMeta> resource) =>
 CreateResourceDefinition(resource.GetType());
 public static ReflectorProperties GetReflectionProperties(this IKubernetesObject <V1ObjectMeta> resource)
 {
     return(resource.EnsureMetadata().GetReflectionProperties());
 }
Esempio n. 19
0
        public async Task PublishAsync(
            IKubernetesObject <V1ObjectMeta> resource,
            string reason,
            string message,
            EventType type = EventType.Normal)
        {
            _logger.LogTrace(
                "Encoding event name with: {resourceName}.{resourceNamespace}.{reason}.{message}.{type}.",
                resource.Name(),
                resource.Namespace(),
                reason,
                message,
                type);
            var eventName =
                Base32.Rfc4648.Encode(
                    SHA512.HashData(
                        Encoding.UTF8.GetBytes($"{resource.Name()}.{resource.Namespace()}.{reason}.{message}.{type}")));

            _logger.LogTrace(@"Search or create event with name ""{name}"".", eventName);
            var @event = await _client.Get <Corev1Event>(eventName, resource.Namespace()) ??
                         new Corev1Event
            {
                Kind       = Corev1Event.KubeKind,
                ApiVersion = $"{Corev1Event.KubeGroup}/{Corev1Event.KubeApiVersion}",
                Metadata   = new V1ObjectMeta
                {
                    Name = eventName,
                    NamespaceProperty = resource.Namespace(),
                    Annotations       = new Dictionary <string, string>
                    {
                        { "nameHash", "sha512" },
                        { "nameEncoding", "Base32 / RFC 4648" },
                    },
                },
                Type               = type.ToString(),
                Reason             = reason,
                Message            = message,
                ReportingComponent = _settings.Name,
                ReportingInstance  = Environment.MachineName,
                Source             = new V1EventSource {
                    Component = _settings.Name
                },
                InvolvedObject = resource.MakeObjectReference(),
                FirstTimestamp = DateTime.UtcNow,
                LastTimestamp  = DateTime.UtcNow,
                Count          = 0,
            };

            @event.Count++;
            @event.LastTimestamp = DateTime.UtcNow;
            _logger.LogTrace(
                "Save event with new count {count} and last timestamp {timestamp}",
                @event.Count,
                @event.LastTimestamp);

            await _client.Save(@event);

            _logger.LogInformation(
                @"Created or updated event with name ""{name}"" to new count {count} on resource ""{kind}/{name}"".",
                eventName,
                @event.Count,
                resource.Kind,
                resource.Name());
        }
Esempio n. 20
0
 public Resource(IKubernetesObject obj, V1ObjectMeta metadata, Func <string, Task <Rest.HttpOperationResponse <V1Status> > > deleter)
 {
     Obj      = obj;
     Metadata = metadata;
     Deleter  = deleter;
 }
Esempio n. 21
0
 public static V1ObjectMeta Metadata(this IKubernetesObject resource)
 {
     return((V1ObjectMeta)resource.GetType().GetProperty(nameof(V1Namespace.Metadata), typeof(V1ObjectMeta))
            ?.GetValue(resource));
 }
Esempio n. 22
0
 public string PortForward(IKubernetesObject <V1ObjectMeta> entity, int localPort, int remotePort)
 {
     return(PortForward(entity.Metadata.Name, entity.Kind, localPort, remotePort, entity.Metadata.Namespace()));
 }
Esempio n. 23
0
 public bool Check(IKubernetesObject kubernetesObject)
 {
     return(_condition?.Invoke(kubernetesObject) ?? true);
 }
Esempio n. 24
0
        private async Task <FetchResult> OpenKubernetesObjectInternal(V1Namespace namespaceMetadata, IKubernetesObject kubernetesObject)
        {
            using var client = new Kubernetes(k8sConfig);
            var buffer = new StringBuilder();
            var title  = "(Unknown)";

            if (namespaceMetadata == null)
            {
                buffer.AppendLine($"Namespace: (Global)");
            }
            else
            {
                buffer.AppendLine($"Namespace: {namespaceMetadata.Metadata.Name}");
            }

            buffer.AppendLine($"Object Type: {kubernetesObject.GetType()}");

            switch (kubernetesObject)
            {
            case V1Namespace ns:
                title = await DescribeObject(client, ns, buffer).ConfigureAwait(false);

                break;

            case V1ComponentStatus cs:
                title = await DescribeObject(client, cs, buffer).ConfigureAwait(false);

                break;

            case V1Node node:
                title = await DescribeObject(client, node, buffer).ConfigureAwait(false);

                break;

            case V1PersistentVolume pv:
                title = await DescribeObject(client, pv, buffer).ConfigureAwait(false);

                break;

            case V1MutatingWebhookConfiguration mutatingWebhookConfiguration:
                title = await DescribeObject(client, mutatingWebhookConfiguration, buffer).ConfigureAwait(false);

                break;

            case V1ValidatingWebhookConfiguration validatingWebhookConfiguration:
                title = await DescribeObject(client, validatingWebhookConfiguration, buffer).ConfigureAwait(false);

                break;

            case V1CustomResourceDefinition crds:
                title = await DescribeObject(client, crds, buffer).ConfigureAwait(false);

                break;

            case V1APIService apiService:
                title = await DescribeObject(client, apiService, buffer).ConfigureAwait(false);

                break;

            case V1beta1CertificateSigningRequest csr:
                title = await DescribeObject(client, csr, buffer).ConfigureAwait(false);

                break;

            case Extensionsv1beta1PodSecurityPolicy psp:
                title = await DescribeObject(client, psp, buffer).ConfigureAwait(false);

                break;

            case V1ClusterRoleBinding clusterrolebinding:
                title = await DescribeObject(client, clusterrolebinding, buffer).ConfigureAwait(false);

                break;

            case V1ClusterRole clusterrole:
                title = await DescribeObject(client, clusterrole, buffer).ConfigureAwait(false);

                break;

            case V1PriorityClass pc:
                title = await DescribeObject(client, pc, buffer).ConfigureAwait(false);

                break;

            case V1beta1CSIDriver csidriver:
                title = await DescribeObject(client, csidriver, buffer).ConfigureAwait(false);

                break;

            case V1beta1CSINode csinode:
                title = await DescribeObject(client, csinode, buffer).ConfigureAwait(false);

                break;

            case V1StorageClass sc:
                title = await DescribeObject(client, sc, buffer).ConfigureAwait(false);

                break;

            case V1VolumeAttachment volumeattachment:
                title = await DescribeObject(client, volumeattachment, buffer).ConfigureAwait(false);

                break;

            case V1ConfigMap cm:
                title = await ChildForm_ConfigMaps.DescribeObject(client, namespaceMetadata, cm, buffer).ConfigureAwait(false);

                break;

            case V1ControllerRevision ctrlrev:
                title = await DescribeObject(client, namespaceMetadata, ctrlrev, buffer).ConfigureAwait(false);

                break;

            case V1DaemonSet ds:
                title = await DescribeObject(client, namespaceMetadata, ds, buffer).ConfigureAwait(false);

                break;

            case V1Deployment deploy:
                title = await DescribeObject(client, namespaceMetadata, deploy, buffer).ConfigureAwait(false);

                break;

            case V1Endpoints ep:
                title = await DescribeObject(client, namespaceMetadata, ep, buffer).ConfigureAwait(false);

                break;

            case V1LimitRange limit:
                title = await DescribeObject(client, namespaceMetadata, limit, buffer).ConfigureAwait(false);

                break;

            case V1PersistentVolumeClaim pvc:
                title = await DescribeObject(client, namespaceMetadata, pvc, buffer).ConfigureAwait(false);

                break;

            case V1Pod pod:
                title = await ChildForm_Pods.DescribeObject(client, namespaceMetadata, pod, buffer).ConfigureAwait(false);

                break;

            case V1PodTemplate podTemplate:
                title = await DescribeObject(client, namespaceMetadata, podTemplate, buffer).ConfigureAwait(false);

                break;

            case V1ReplicationController replCtrl:
                title = await DescribeObject(client, namespaceMetadata, replCtrl, buffer).ConfigureAwait(false);

                break;

            case V1ResourceQuota quota:
                title = await DescribeObject(client, namespaceMetadata, quota, buffer).ConfigureAwait(false);

                break;

            case V1Secret secret:
                title = await DescribeObject(client, namespaceMetadata, secret, buffer).ConfigureAwait(false);

                break;

            case V1ServiceAccount sa:
                title = await DescribeObject(client, namespaceMetadata, sa, buffer).ConfigureAwait(false);

                break;

            case V1Service svc:
                title = await DescribeObject(client, namespaceMetadata, svc, buffer).ConfigureAwait(false);

                break;

            case V1ReplicaSet rs:
                title = await DescribeObject(client, namespaceMetadata, rs, buffer).ConfigureAwait(false);

                break;

            case V1StatefulSet sts:
                title = await DescribeObject(client, namespaceMetadata, sts, buffer).ConfigureAwait(false);

                break;

            case V1HorizontalPodAutoscaler hpa:
                title = await DescribeObject(client, namespaceMetadata, hpa, buffer).ConfigureAwait(false);

                break;

            case V1beta1CronJob cj:
                title = await DescribeObject(client, namespaceMetadata, cj, buffer).ConfigureAwait(false);

                break;

            case V1Job job:
                title = await DescribeObject(client, namespaceMetadata, job, buffer).ConfigureAwait(false);

                break;

            case Extensionsv1beta1Ingress ing:
                title = await DescribeObject(client, namespaceMetadata, ing, buffer).ConfigureAwait(false);

                break;

            case V1beta1PodDisruptionBudget pdb:
                title = await DescribeObject(client, namespaceMetadata, pdb, buffer).ConfigureAwait(false);

                break;

            case V1RoleBinding rolebinding:
                title = await DescribeObject(client, namespaceMetadata, rolebinding, buffer).ConfigureAwait(false);

                break;

            case V1Role role:
                title = await DescribeObject(client, namespaceMetadata, role, buffer).ConfigureAwait(false);

                break;

            case V1Lease lease:
                title = await DescribeObject(client, namespaceMetadata, lease, buffer).ConfigureAwait(false);

                break;

            case V1Event @event:
                title = await DescribeObject(client, namespaceMetadata, @event, buffer).ConfigureAwait(false);

                break;

            case V1beta1NetworkPolicy netpol:
                title = await DescribeObject(client, namespaceMetadata, netpol, buffer).ConfigureAwait(false);

                break;

            default:
                break;
            }

            return(new FetchResult(title, buffer.ToString()));
        }
Esempio n. 25
0
 /// <summary>Removes all <see cref="V1OwnerReference">owner references</see> that match the given object, and returns true if
 /// any were removed.
 /// </summary>
 /// <param name="obj">the object meta<see cref="V1ObjectMeta"/></param>
 /// <param name="owner">the owner of the object<see cref="V1ObjectMeta"/></param>
 /// <returns>true if any were removed</returns>
 public static bool RemoveOwnerReferences(
     this IMetadata <V1ObjectMeta> obj,
     IKubernetesObject <V1ObjectMeta> owner) =>
 RemoveOwnerReferences(obj, r => r.Matches(owner));
Esempio n. 26
0
 /// <summary>Determines whether one object is owned by another.</summary>
 /// <param name="obj">the object meta<see cref="V1ObjectMeta"/></param>
 /// <param name="owner">the owner of the object<see cref="V1ObjectMeta"/></param>
 /// <returns>true if owned by obj</returns>
 public static bool IsOwnedBy(this IMetadata <V1ObjectMeta> obj, IKubernetesObject <V1ObjectMeta> owner) =>
 FindOwnerReference(obj, owner) >= 0;
Esempio n. 27
0
 /// <summary>Gets <see cref="V1OwnerReference"/> that matches the given object, or null if no matching reference exists.</summary>
 /// <param name="obj">the object meta<see cref="V1ObjectMeta"/></param>
 /// <param name="owner">the owner of the object<see cref="V1ObjectMeta"/></param>
 /// <returns>the <see cref="V1OwnerReference"/> that matches the given object, or null if no matching reference exists.</returns>
 public static V1OwnerReference GetOwnerReference(
     this IMetadata <V1ObjectMeta> obj,
     IKubernetesObject <V1ObjectMeta> owner) =>
 GetOwnerReference(obj, r => r.Matches(owner));
Esempio n. 28
0
 public IEventManager.AsyncStaticPublisher CreatePublisher(
     IKubernetesObject <V1ObjectMeta> resource,
     string reason,
     string message,
     EventType type = EventType.Normal)
 => () => PublishAsync(resource, reason, message, type);
Esempio n. 29
0
 internal static CustomEntityDefinition CreateResourceDefinition(
     this IKubernetesObject <V1ObjectMeta> kubernetesEntity) =>
 CreateResourceDefinition(kubernetesEntity.GetType());
 public static V1OwnerReference MakeOwnerReference(this IKubernetesObject <V1ObjectMeta> kubernetesObject)
 => new V1OwnerReference(
     kubernetesObject.ApiVersion,
     kubernetesObject.Kind,
     kubernetesObject.Metadata.Name,
     kubernetesObject.Metadata.Uid);