Skip to content

Commit

Permalink
Add client support for Swarm Logs and Swarm Config (#589)
Browse files Browse the repository at this point in the history
* expose Swam Config as client.Configs

* Expose Swam Service Logs

* send SwarmConfigSpec to api

* Update src/Docker.DotNet/Endpoints/ISwarmOperations.cs

Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>

* Update src/Docker.DotNet/Endpoints/ISwarmOperations.cs

Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>

* rename to standard
add logging test

* add logging test

fix naming convention

* Update src/Docker.DotNet/Endpoints/IConfigsOperations.cs

Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>

* Update src/Docker.DotNet/Endpoints/IConfigsOperations.cs

Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>

* Update src/Docker.DotNet/Endpoints/ConfigsOperations.cs

Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>

* Add Config Tests, some Renaming fixes

* updated test with retry and increased buffer.  Improved cancelation handling.

---------

Co-authored-by: Jasim Schluter <Jasim.Schluter@pacom.com>
Co-authored-by: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
  • Loading branch information
3 people committed Apr 13, 2023
1 parent 3ca9743 commit 1c3a067
Show file tree
Hide file tree
Showing 9 changed files with 745 additions and 381 deletions.
2 changes: 0 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# Autodetect text files
* text=auto

# Definitively text files
*.cs text
3 changes: 3 additions & 0 deletions src/Docker.DotNet/DockerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ internal DockerClient(DockerClientConfiguration configuration, Version requested
System = new SystemOperations(this);
Networks = new NetworkOperations(this);
Secrets = new SecretsOperations(this);
Configs = new ConfigOperations(this);
Swarm = new SwarmOperations(this);
Tasks = new TasksOperations(this);
Volumes = new VolumeOperations(this);
Expand Down Expand Up @@ -136,6 +137,8 @@ await sock.ConnectAsync(new Microsoft.Net.Http.Client.UnixDomainSocketEndPoint(p

public ISecretsOperations Secrets { get; }

public IConfigOperations Configs { get; }

public ISwarmOperations Swarm { get; }

public ITasksOperations Tasks { get; }
Expand Down
58 changes: 58 additions & 0 deletions src/Docker.DotNet/Endpoints/ConfigsOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet.Models;

namespace Docker.DotNet
{
internal class ConfigOperations : IConfigOperations
{
private readonly DockerClient _client;

internal ConfigOperations(DockerClient client)
{
this._client = client;
}

async Task<IList<SwarmConfig>> IConfigOperations.ListConfigsAsync(CancellationToken cancellationToken)
{
var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, "configs", cancellationToken).ConfigureAwait(false);
return this._client.JsonSerializer.DeserializeObject<IList<SwarmConfig>>(response.Body);
}

async Task<SwarmCreateConfigResponse> IConfigOperations.CreateConfigAsync(SwarmCreateConfigParameters body, CancellationToken cancellationToken)
{
if (body == null)
{
throw new ArgumentNullException(nameof(body));
}

var data = new JsonRequestContent<SwarmConfigSpec>(body.Config, this._client.JsonSerializer);
var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Post, "configs/create", null, data, cancellationToken).ConfigureAwait(false);
return this._client.JsonSerializer.DeserializeObject<SwarmCreateConfigResponse>(response.Body);
}

async Task<SwarmConfig> IConfigOperations.InspectConfigAsync(string id, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException(nameof(id));
}

var response = await this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Get, $"configs/{id}", cancellationToken).ConfigureAwait(false);
return this._client.JsonSerializer.DeserializeObject<SwarmConfig>(response.Body);
}

Task IConfigOperations.RemoveConfigAsync(string id, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException(nameof(id));
}

return this._client.MakeRequestAsync(this._client.NoErrorHandlers, HttpMethod.Delete, $"configs/{id}", cancellationToken);
}
}
}
53 changes: 53 additions & 0 deletions src/Docker.DotNet/Endpoints/IConfigsOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet.Models;

namespace Docker.DotNet
{
public interface IConfigOperations
{
/// <summary>
/// List configs
/// </summary>
/// <remarks>
/// 200 - No error.
/// 500 - Server error.
/// </remarks>
Task<IList<SwarmConfig>> ListConfigsAsync(CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Create a configs
/// </summary>
/// <remarks>
/// 201 - No error.
/// 406 - Server error or node is not part of a swarm.
/// 409 - Name conflicts with an existing object.
/// 500 - Server error.
/// </remarks>
Task<SwarmCreateConfigResponse> CreateConfigAsync(SwarmCreateConfigParameters body, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Inspect a configs
/// </summary>
/// <remarks>
/// 200 - No error.
/// 404 - Secret not found.
/// 406 - Node is not part of a swarm.
/// 500 - Server error.
/// </remarks>
/// <param name="id">ID of the config.</param>
Task<SwarmConfig> InspectConfigAsync(string id, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Remove a configs
/// </summary>
/// <remarks>
/// 204 - No error.
/// 404 - Secret not found.
/// 500 - Server error.
/// </remarks>
/// <param name="id">ID of the config.</param>
Task RemoveConfigAsync(string id, CancellationToken cancellationToken = default(CancellationToken));
}
}
37 changes: 37 additions & 0 deletions src/Docker.DotNet/Endpoints/ISwarmOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Docker.DotNet.Models;
using System.Threading;
using System.IO;

namespace Docker.DotNet
{
Expand Down Expand Up @@ -154,6 +155,42 @@ public interface ISwarmOperations
/// <param name="id">ID or name of service.</param>
Task RemoveServiceAsync(string id, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Gets <c>stdout</c> and <c>stderr</c> logs from services.
/// </summary>
/// <param name="id">The ID or name of the service.</param>
/// <param name="parameters">Specifics of how to perform the operation.</param>
/// <param name="cancellationToken">When triggered, the operation will stop at the next available time, if possible.</param>
/// <returns>A <see cref="Task"/> that will complete once all log lines have been read.</returns>
/// <remarks>
/// This method is only suited for services with the <c>json-file</c> or <c>journald</c> logging driver.
///
/// HTTP GET /services/(id)/logs
///
/// 101 - Logs returned as a stream.
/// 200 - Logs returned as a string in response body.
/// 404 - No such service.
/// 500 - Server error.
/// 503 - Node is not part of a swarm.
/// </remarks>
Task<Stream> GetServiceLogsAsync(string id, ServiceLogsParameters parameters, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Gets <c>stdout</c> and <c>stderr</c> logs from services.
/// </summary>
/// <param name="id">The ID or name of the service.</param>
/// <param name="tty">Indicates whether the service was created with a TTY. If <see langword="false"/>, the returned stream is multiplexed.</param>
/// <param name="parameters">Specifics of how to perform the operation.</param>
/// <param name="cancellationToken">When triggered, the operation will stop at the next available time, if possible.</param>
/// <returns>
/// A <see cref="Task{TResult}"/> that resolves to a <see cref="MultiplexedStream"/>, which provides the log information.
/// If the service wasn't created with a TTY, this stream is multiplexed.
/// </returns>
/// <remarks>
/// This method is only suited for services with the <c>json-file</c> or <c>journald</c> logging driver.
/// </remarks>
Task<MultiplexedStream> GetServiceLogsAsync(string id, bool tty, ServiceLogsParameters parameters, CancellationToken cancellationToken = default(CancellationToken));

#endregion Services

#region Nodes
Expand Down
Loading

0 comments on commit 1c3a067

Please sign in to comment.