using MySqlConnector;
using OTSSignsOrchestrator.Core.Models.DTOs;
namespace OTSSignsOrchestrator.Core.Services;
///
/// Abstraction for Docker CLI stack operations (deploy, remove, list, inspect).
/// Implementations may use local docker CLI or SSH-based remote execution.
///
public interface IDockerCliService
{
Task DeployStackAsync(string stackName, string composeYaml, bool resolveImage = false);
Task RemoveStackAsync(string stackName);
Task> ListStacksAsync();
Task> InspectStackServicesAsync(string stackName);
/// Ensures a directory exists on the target host (equivalent to mkdir -p).
Task EnsureDirectoryAsync(string path);
///
/// Ensures the required folders exist on an NFS export, creating any that are missing.
/// If is non-empty, creates it first as a subfolder of the export,
/// then creates the volume folders inside it.
/// Temporarily mounts the NFS export on the Docker host to create the directories.
///
Task EnsureNfsFoldersAsync(
string nfsServer,
string nfsExport,
IEnumerable folderNames,
string? nfsExportFolder = null);
///
/// Same as but returns the error message on failure
/// so callers can surface actionable diagnostics.
///
Task<(bool Success, string? Error)> EnsureNfsFoldersWithErrorAsync(
string nfsServer,
string nfsExport,
IEnumerable folderNames,
string? nfsExportFolder = null);
///
/// Removes all Docker volumes whose names start with _.
/// Volumes currently in use by running containers will be skipped.
/// Safe for NFS volumes since data lives on the remote export, not in the local volume.
///
Task RemoveStackVolumesAsync(string stackName);
///
/// Lists all nodes in the Docker Swarm cluster.
/// Must be executed against a Swarm manager node.
///
Task> ListNodesAsync();
///
/// Force-updates a service so all its tasks are restarted and pick up any changed
/// secrets or config (equivalent to docker service update --force).
///
Task ForceUpdateServiceAsync(string serviceName);
///
/// Opens a to a remote MySQL server through the
/// implementation's transport (e.g. an SSH tunnel). The caller must dispose
/// both the connection and the returned tunnel handle when finished.
///
///
/// A tuple of (connection, tunnel). tunnel is
/// and MUST be disposed after the connection is closed.
///
Task<(MySqlConnection Connection, IDisposable Tunnel)> OpenMySqlConnectionAsync(
string mysqlHost, int port,
string adminUser, string adminPassword);
///
/// Executes ALTER USER … IDENTIFIED BY … on a remote MySQL server via
/// .
///
Task<(bool Success, string Error)> AlterMySqlUserPasswordAsync(
string mysqlHost, int port,
string adminUser, string adminPassword,
string targetUser, string newPassword);
///
/// Atomically swaps one secret reference on a running service:
/// removes and adds ,
/// preserving the in-container path as (defaults to
/// when null, keeping the same /run/secrets/ filename).
///
Task ServiceSwapSecretAsync(string serviceName, string oldSecretName, string newSecretName, string? targetAlias = null);
}
public class StackInfo
{
public string Name { get; set; } = string.Empty;
public int ServiceCount { get; set; }
}
public class ServiceInfo
{
public string Name { get; set; } = string.Empty;
public string Image { get; set; } = string.Empty;
public string Replicas { get; set; } = string.Empty;
}