/// <summary> /// Create a namespaced custom object. /// </summary> /// <typeparam name="T">The custom object type.</typeparam> /// <param name="k8s">The <see cref="Kubernetes"/> client.</param> /// <param name="body">The object data.</param> /// <param name="name">Specifies the object name.</param> /// <param name="namespaceParameter">That target Kubernetes namespace.</param> /// <param name="dryRun"> /// When present, indicates that modifications should not be persisted. An invalid /// or unrecognized dryRun directive will result in an error response and no further /// processing of the request. Valid values are: - All: all dry run stages will be /// processed /// </param> /// <param name="fieldManager"> /// fieldManager is a name associated with the actor or entity that is making these /// changes. The value must be less than or 128 characters long, and only contain /// printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. /// </param> /// <param name="cancellationToken">Optionally specifies a cancellation token.</param> /// <returns>The new object.</returns> public static async Task <T> CreateNamespacedCustomObjectAsync <T>( this IKubernetes k8s, T body, string name, string namespaceParameter, string dryRun = null, string fieldManager = null, CancellationToken cancellationToken = default) where T : IKubernetesObject <V1ObjectMeta>, new() { await SyncContext.Clear; Covenant.Requires <ArgumentNullException>(body != null, nameof(body)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(name), nameof(name)); body.Metadata.Name = name; var typeMetadata = body.GetKubernetesTypeMetadata(); var result = await k8s.CreateNamespacedCustomObjectAsync( body : body, group : typeMetadata.Group, version : typeMetadata.ApiVersion, namespaceParameter : namespaceParameter, plural : typeMetadata.PluralName, dryRun : dryRun, fieldManager : fieldManager, pretty : false, cancellationToken : cancellationToken); return(((JsonElement)result).Deserialize <T>(options: serializeOptions)); }
/// <summary> /// Creates or replaces a namespace scoped custom object of the specified generic object type, /// depending on whether the object already exists in the cluster. /// </summary> /// <typeparam name="T">The custom object type.</typeparam> /// <param name="k8s">The <see cref="Kubernetes"/> client.</param> /// <param name="body">Specifies the new object data.</param> /// <param name="namespaceParameter">That target Kubernetes namespace.</param> /// <param name="name">Specifies the object name.</param> /// <param name="dryRun"> /// When present, indicates that modifications should not be persisted. An invalid /// or unrecognized dryRun directive will result in an error response and no further /// processing of the request. Valid values are: - All: all dry run stages will be /// processed /// </param> /// <param name="fieldManager"> /// fieldManager is a name associated with the actor or entity that is making these /// changes. The value must be less than or 128 characters long, and only contain /// printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. /// </param> /// <param name="cancellationToken">Optionally specifies a cancellation token.</param> /// <returns>The updated object.</returns> public static async Task <T> UpsertNamespacedCustomObjectAsync <T>( this IKubernetes k8s, T body, string namespaceParameter, string name, string dryRun = null, string fieldManager = null, CancellationToken cancellationToken = default(CancellationToken)) where T : IKubernetesObject <V1ObjectMeta>, new() { await SyncContext.Clear; Covenant.Requires <ArgumentNullException>(body != null, nameof(body)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(namespaceParameter), nameof(namespaceParameter)); Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(name), nameof(name)); // $todo(jefflill): Investigate fixing race condition: // // https://github.com/nforgeio/neonKUBE/issues/1578 // We're going to try fetching the resource first. If it doesn't exist, we'll // create it otherwise we'll replace it. try { await k8s.ReadNamespacedCustomObjectAsync <T>(namespaceParameter, name, cancellationToken); } catch (HttpOperationException e) { if (e.Response.StatusCode == HttpStatusCode.NotFound) { return(await k8s.CreateNamespacedCustomObjectAsync <T>( body : body, name : name, namespaceParameter : namespaceParameter, dryRun : dryRun, fieldManager : fieldManager, cancellationToken : cancellationToken)); } else { throw; } } return(await k8s.ReplaceNamespacedCustomObjectAsync <T>( body : body, namespaceParameter : namespaceParameter, name : name, dryRun : dryRun, fieldManager : fieldManager, cancellationToken : cancellationToken)); }
public static async Task <TResource> CreateOrReplaceNamespacedCustomObjectAsync <TResource>( this IKubernetes client, string group, string version, string plural, TResource resource, CancellationToken cancellationToken) where TResource : class, IKubernetesObject <V1ObjectMeta>, new() { if (client is null) { throw new ArgumentNullException(nameof(client)); } if (string.IsNullOrEmpty(group)) { throw new ArgumentException($"'{nameof(group)}' cannot be null or empty", nameof(group)); } if (string.IsNullOrEmpty(version)) { throw new ArgumentException($"'{nameof(version)}' cannot be null or empty", nameof(version)); } if (string.IsNullOrEmpty(plural)) { throw new ArgumentException($"'{nameof(plural)}' cannot be null or empty", nameof(plural)); } if (resource is null) { throw new ArgumentNullException(nameof(resource)); } var list = _serializers.Convert <KubernetesList <TResource> >(await client.ListNamespacedCustomObjectAsync( group: group, version: version, namespaceParameter: resource.Namespace(), plural: plural, fieldSelector: $"metadata.name={resource.Name()}", cancellationToken: cancellationToken)); var resourceExisting = list.Items.SingleOrDefault(); if (resourceExisting != null) { resource.Metadata.ResourceVersion = resourceExisting.ResourceVersion(); return(_serializers.Convert <TResource>(await client.ReplaceNamespacedCustomObjectAsync( body: resource, group: group, version: version, namespaceParameter: resource.Namespace(), plural: plural, name: resource.Name(), cancellationToken: cancellationToken))); } else { return(_serializers.Convert <TResource>(await client.CreateNamespacedCustomObjectAsync( body: resource, group: group, version: version, namespaceParameter: resource.Namespace(), plural: plural, cancellationToken: cancellationToken))); } }
/// <summary> /// Creates a new namespaced custom object of the specified type /// </summary> /// <typeparam name="TResource">The type of custom object to create</typeparam> /// <param name="kubernetes">The extended <see cref="IKubernetes"/></param> /// <param name="resource">The resource to create</param> /// <param name="namespaceParameter">The namespace for which to create the specified custom object</param> /// <param name="pretty">A boolean indicating whether or not the resource should be pretty-printed</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/></param> /// <returns>The newly created resource</returns> public static async Task <TResource> CreateNamespacedCustomObjectAsync <TResource>(this IKubernetes kubernetes, TResource resource, string namespaceParameter, bool pretty = false, CancellationToken cancellationToken = default) where TResource : class, ICustomResource { return(await kubernetes.CreateNamespacedCustomObjectAsync(resource, resource.Definition.Group, resource.Definition.Version, namespaceParameter, resource.Definition.Plural, null, null, pretty? "true" : null, cancellationToken) as TResource); }