feat: Moves commands into cli-client module, adds tests, needs implemented in the executable.

This commit is contained in:
2024-12-11 14:41:06 -05:00
parent ddb5e6767a
commit c1a14ea855
8 changed files with 276 additions and 280 deletions

View File

@@ -5,34 +5,25 @@ import FileClient
import Foundation
import ShellClient
public extension DependencyValues {
var cliClient: CliClient {
get { self[CliClient.self] }
set { self[CliClient.self] = newValue }
}
}
public extension CliClient {
@DependencyClient
public struct CliClient: Sendable {
public var runCommand: @Sendable ([String], Bool, ShellCommand.Shell) async throws -> Void
public func runCommand(
func runCommand(
quiet: Bool,
shell: ShellCommand.Shell,
_ args: [String]
) async throws {
try await runCommand(args, quiet, shell)
try await runCommand(.init(arguments: args, quiet: quiet, shell: shell))
}
public func runCommand(
func runCommand(
quiet: Bool,
shell: ShellCommand.Shell,
_ args: String...
) async throws {
try await runCommand(args, quiet, shell)
try await runCommand(quiet: quiet, shell: shell, args)
}
public func runPlaybookCommand(_ options: PlaybookOptions) async throws {
func runPlaybookCommand(_ options: PlaybookOptions) async throws {
@Dependency(\.configurationClient) var configurationClient
@Dependency(\.logger) var logger
@@ -46,7 +37,7 @@ public struct CliClient: Sendable {
let inventoryPath = ensuredInventoryPath(
options.inventoryFilePath,
configuration: configuration,
playboodDirectory: playbookDirectory
playbookDirectory: playbookDirectory
)
logger.trace("Inventory path: \(inventoryPath)")
@@ -72,7 +63,7 @@ public struct CliClient: Sendable {
)
}
public func runVaultCommand(_ options: VaultOptions) async throws {
func runVaultCommand(_ options: VaultOptions) async throws {
@Dependency(\.configurationClient) var configurationClient
@Dependency(\.fileClient) var fileClient
@Dependency(\.logger) var logger
@@ -98,6 +89,10 @@ public struct CliClient: Sendable {
arguments.append(contentsOf: ["--encrypt-vault-id", id])
}
arguments.append(vaultFilePath)
logger.trace("Running vault command with arguments: \(arguments)")
try await runCommand(
quiet: options.quiet,
shell: options.shell.shellOrDefault,
@@ -106,89 +101,6 @@ public struct CliClient: Sendable {
}
}
public extension CliClient {
struct PlaybookOptions: Sendable, Equatable {
let arguments: [String]
let configuration: Configuration?
let inventoryFilePath: String?
let playbookDirectory: String?
let quiet: Bool
let shell: String?
public init(
arguments: [String],
configuration: Configuration? = nil,
inventoryFilePath: String? = nil,
playbookDirectory: String? = nil,
quiet: Bool,
shell: String? = nil
) {
self.arguments = arguments
self.configuration = configuration
self.inventoryFilePath = inventoryFilePath
self.playbookDirectory = playbookDirectory
self.quiet = quiet
self.shell = shell
}
}
struct VaultOptions: Equatable, Sendable {
let arguments: [String]
let configuration: Configuration?
let quiet: Bool
let shell: String?
let vaultFilePath: String?
public init(
arguments: [String],
configuration: Configuration? = nil,
quiet: Bool,
shell: String?,
vaultFilePath: String? = nil
) {
self.arguments = arguments
self.configuration = configuration
self.quiet = quiet
self.shell = shell
self.vaultFilePath = vaultFilePath
}
}
}
extension CliClient: DependencyKey {
public static func live(
env: [String: String]
) -> Self {
@Dependency(\.logger) var logger
return .init { args, quiet, shell in
@Dependency(\.asyncShellClient) var shellClient
if !quiet {
try await shellClient.foreground(.init(
shell: shell,
environment: ProcessInfo.processInfo.environment,
in: nil,
args
))
} else {
try await shellClient.background(.init(
shell: shell,
environment: ProcessInfo.processInfo.environment,
in: nil,
args
))
}
}
}
public static var liveValue: CliClient {
.live(env: ProcessInfo.processInfo.environment)
}
public static let testValue: CliClient = Self()
}
private extension ConfigurationClient {
func ensuredConfiguration(_ optionalConfig: Configuration?) async throws -> Configuration {
guard let config = optionalConfig else {
@@ -222,11 +134,11 @@ private extension Optional where Wrapped == String {
private func ensuredInventoryPath(
_ optionalInventoryPath: String?,
configuration: Configuration,
playboodDirectory: String
playbookDirectory: String
) -> String {
guard let path = optionalInventoryPath else {
guard let path = configuration.playbook?.inventory else {
return "\(playboodDirectory)/\(Constants.inventoryFileName)"
return "\(playbookDirectory)/\(Constants.inventoryFileName)"
}
return path
}
@@ -250,3 +162,5 @@ enum CliClientError: Error {
case playbookDirectoryNotFound
case vaultFileNotFound
}
extension ShellCommand.Shell: @retroactive @unchecked Sendable {}

View File

@@ -0,0 +1,139 @@
import ConfigurationClient
import Dependencies
import DependenciesMacros
import Foundation
import ShellClient
public extension DependencyValues {
var cliClient: CliClient {
get { self[CliClient.self] }
set { self[CliClient.self] = newValue }
}
}
@DependencyClient
public struct CliClient: Sendable {
public var runCommand: @Sendable (RunCommandOptions) async throws -> Void
}
public extension CliClient {
struct PlaybookOptions: Sendable, Equatable {
let arguments: [String]
let configuration: Configuration?
let inventoryFilePath: String?
let playbookDirectory: String?
let quiet: Bool
let shell: String?
public init(
arguments: [String],
configuration: Configuration? = nil,
inventoryFilePath: String? = nil,
playbookDirectory: String? = nil,
quiet: Bool,
shell: String? = nil
) {
self.arguments = arguments
self.configuration = configuration
self.inventoryFilePath = inventoryFilePath
self.playbookDirectory = playbookDirectory
self.quiet = quiet
self.shell = shell
}
}
struct RunCommandOptions: Sendable, Equatable {
public let arguments: [String]
public let quiet: Bool
public let shell: ShellCommand.Shell
public init(
arguments: [String],
quiet: Bool,
shell: ShellCommand.Shell
) {
self.arguments = arguments
self.quiet = quiet
self.shell = shell
}
}
struct VaultOptions: Equatable, Sendable {
let arguments: [String]
let configuration: Configuration?
let quiet: Bool
let shell: String?
let vaultFilePath: String?
public init(
arguments: [String],
configuration: Configuration? = nil,
quiet: Bool,
shell: String?,
vaultFilePath: String? = nil
) {
self.arguments = arguments
self.configuration = configuration
self.quiet = quiet
self.shell = shell
self.vaultFilePath = vaultFilePath
}
}
}
extension CliClient: DependencyKey {
public static func live(
env: [String: String]
) -> Self {
@Dependency(\.logger) var logger
return .init { options in
@Dependency(\.asyncShellClient) var shellClient
if !options.quiet {
try await shellClient.foreground(.init(
shell: options.shell,
environment: ProcessInfo.processInfo.environment,
in: nil,
options.arguments
))
} else {
try await shellClient.background(.init(
shell: options.shell,
environment: ProcessInfo.processInfo.environment,
in: nil,
options.arguments
))
}
}
}
public static var liveValue: CliClient {
.live(env: ProcessInfo.processInfo.environment)
}
public static let testValue: CliClient = Self()
public static func capturing(_ client: CapturingClient) -> Self {
.init { options in
await client.set(options)
}
}
public actor CapturingClient: Sendable {
public private(set) var quiet: Bool?
public private(set) var shell: ShellCommand.Shell?
public private(set) var arguments: [String]?
public init() {}
public func set(
_ options: RunCommandOptions
) {
quiet = options.quiet
shell = options.shell
arguments = options.arguments
}
}
}