feat: Moves commands into cli-client module, adds tests, needs implemented in the executable.
This commit is contained in:
@@ -39,21 +39,14 @@ let package = Package(
|
|||||||
"ConfigurationClient",
|
"ConfigurationClient",
|
||||||
.product(name: "Dependencies", package: "swift-dependencies"),
|
.product(name: "Dependencies", package: "swift-dependencies"),
|
||||||
.product(name: "DependenciesMacros", package: "swift-dependencies"),
|
.product(name: "DependenciesMacros", package: "swift-dependencies"),
|
||||||
.product(name: "ShellClient", package: "swift-shell-client"),
|
.product(name: "ShellClient", package: "swift-shell-client")
|
||||||
.product(name: "TOMLKit", package: "TOMLKit")
|
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "CliClientTests",
|
name: "CliClientTests",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"CliClient",
|
"CliClient",
|
||||||
.product(name: "TOMLKit", package: "TOMLKit")
|
"TestSupport"
|
||||||
],
|
|
||||||
resources: [
|
|
||||||
.copy("Resources/config.json"),
|
|
||||||
.copy("Resources/.hparc"),
|
|
||||||
.copy("Resources/vault.yml"),
|
|
||||||
.copy("Resources/hpa-playbook")
|
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
.target(
|
.target(
|
||||||
|
|||||||
@@ -5,34 +5,25 @@ import FileClient
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ShellClient
|
import ShellClient
|
||||||
|
|
||||||
public extension DependencyValues {
|
public extension CliClient {
|
||||||
var cliClient: CliClient {
|
|
||||||
get { self[CliClient.self] }
|
|
||||||
set { self[CliClient.self] = newValue }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DependencyClient
|
func runCommand(
|
||||||
public struct CliClient: Sendable {
|
|
||||||
public var runCommand: @Sendable ([String], Bool, ShellCommand.Shell) async throws -> Void
|
|
||||||
|
|
||||||
public func runCommand(
|
|
||||||
quiet: Bool,
|
quiet: Bool,
|
||||||
shell: ShellCommand.Shell,
|
shell: ShellCommand.Shell,
|
||||||
_ args: [String]
|
_ args: [String]
|
||||||
) async throws {
|
) 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,
|
quiet: Bool,
|
||||||
shell: ShellCommand.Shell,
|
shell: ShellCommand.Shell,
|
||||||
_ args: String...
|
_ args: String...
|
||||||
) async throws {
|
) 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(\.configurationClient) var configurationClient
|
||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
|
|
||||||
@@ -46,7 +37,7 @@ public struct CliClient: Sendable {
|
|||||||
let inventoryPath = ensuredInventoryPath(
|
let inventoryPath = ensuredInventoryPath(
|
||||||
options.inventoryFilePath,
|
options.inventoryFilePath,
|
||||||
configuration: configuration,
|
configuration: configuration,
|
||||||
playboodDirectory: playbookDirectory
|
playbookDirectory: playbookDirectory
|
||||||
)
|
)
|
||||||
logger.trace("Inventory path: \(inventoryPath)")
|
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(\.configurationClient) var configurationClient
|
||||||
@Dependency(\.fileClient) var fileClient
|
@Dependency(\.fileClient) var fileClient
|
||||||
@Dependency(\.logger) var logger
|
@Dependency(\.logger) var logger
|
||||||
@@ -98,6 +89,10 @@ public struct CliClient: Sendable {
|
|||||||
arguments.append(contentsOf: ["--encrypt-vault-id", id])
|
arguments.append(contentsOf: ["--encrypt-vault-id", id])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arguments.append(vaultFilePath)
|
||||||
|
|
||||||
|
logger.trace("Running vault command with arguments: \(arguments)")
|
||||||
|
|
||||||
try await runCommand(
|
try await runCommand(
|
||||||
quiet: options.quiet,
|
quiet: options.quiet,
|
||||||
shell: options.shell.shellOrDefault,
|
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 {
|
private extension ConfigurationClient {
|
||||||
func ensuredConfiguration(_ optionalConfig: Configuration?) async throws -> Configuration {
|
func ensuredConfiguration(_ optionalConfig: Configuration?) async throws -> Configuration {
|
||||||
guard let config = optionalConfig else {
|
guard let config = optionalConfig else {
|
||||||
@@ -222,11 +134,11 @@ private extension Optional where Wrapped == String {
|
|||||||
private func ensuredInventoryPath(
|
private func ensuredInventoryPath(
|
||||||
_ optionalInventoryPath: String?,
|
_ optionalInventoryPath: String?,
|
||||||
configuration: Configuration,
|
configuration: Configuration,
|
||||||
playboodDirectory: String
|
playbookDirectory: String
|
||||||
) -> String {
|
) -> String {
|
||||||
guard let path = optionalInventoryPath else {
|
guard let path = optionalInventoryPath else {
|
||||||
guard let path = configuration.playbook?.inventory else {
|
guard let path = configuration.playbook?.inventory else {
|
||||||
return "\(playboodDirectory)/\(Constants.inventoryFileName)"
|
return "\(playbookDirectory)/\(Constants.inventoryFileName)"
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
@@ -250,3 +162,5 @@ enum CliClientError: Error {
|
|||||||
case playbookDirectoryNotFound
|
case playbookDirectoryNotFound
|
||||||
case vaultFileNotFound
|
case vaultFileNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ShellCommand.Shell: @retroactive @unchecked Sendable {}
|
||||||
139
Sources/CliClient/Interface.swift
Normal file
139
Sources/CliClient/Interface.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,124 +1,121 @@
|
|||||||
// @_spi(Internal) import CliClient
|
import CliClient
|
||||||
// import Dependencies
|
import ConfigurationClient
|
||||||
// import Foundation
|
import Dependencies
|
||||||
// import ShellClient
|
import Foundation
|
||||||
// import Testing
|
import ShellClient
|
||||||
// import TOMLKit
|
import Testing
|
||||||
//
|
import TestSupport
|
||||||
// @Suite("CliClientTests")
|
|
||||||
// struct CliClientTests {
|
|
||||||
//
|
|
||||||
// @Test
|
|
||||||
// func testLiveFileClient() {
|
|
||||||
// withTestLogger(key: "testFindConfigPaths", logLevel: .trace) {
|
|
||||||
// $0.fileClient = .liveValue
|
|
||||||
// } operation: {
|
|
||||||
// @Dependency(\.fileClient) var fileClient
|
|
||||||
// let homeDir = fileClient.homeDir()
|
|
||||||
// #expect(fileClient.isDirectory(homeDir))
|
|
||||||
// #expect(fileClient.isReadable(homeDir))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test
|
|
||||||
// func testFindConfigPaths() throws {
|
|
||||||
// withTestLogger(key: "testFindConfigPaths", logLevel: .trace) {
|
|
||||||
// $0.fileClient = .liveValue
|
|
||||||
// } operation: {
|
|
||||||
// @Dependency(\.logger) var logger
|
|
||||||
// let configURL = Bundle.module.url(forResource: "config", withExtension: "json")!
|
|
||||||
// var env = [
|
|
||||||
// "HPA_CONFIG_FILE": path(for: configURL)
|
|
||||||
// ]
|
|
||||||
// var url = try? findConfigurationFiles(env: env)
|
|
||||||
// #expect(url != nil)
|
|
||||||
//
|
|
||||||
// env["HPA_CONFIG_FILE"] = nil
|
|
||||||
// env["HPA_CONFIG_HOME"] = path(for: configURL.deletingLastPathComponent())
|
|
||||||
// url = try? findConfigurationFiles(env: env)
|
|
||||||
// #expect(url != nil)
|
|
||||||
//
|
|
||||||
// env["HPA_CONFIG_HOME"] = nil
|
|
||||||
// env["PWD"] = path(for: configURL.deletingLastPathComponent())
|
|
||||||
// url = try? findConfigurationFiles(env: env)
|
|
||||||
// #expect(url != nil)
|
|
||||||
//
|
|
||||||
// env["PWD"] = nil
|
|
||||||
// env["XDG_CONFIG_HOME"] = path(for: configURL.deletingLastPathComponent())
|
|
||||||
// url = try? findConfigurationFiles(env: env)
|
|
||||||
// #expect(url != nil)
|
|
||||||
//
|
|
||||||
// withDependencies {
|
|
||||||
// $0.fileClient.homeDir = { configURL.deletingLastPathComponent() }
|
|
||||||
// } operation: {
|
|
||||||
// url = try? findConfigurationFiles(env: [:])
|
|
||||||
// #expect(url != nil)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// url = try? findConfigurationFiles(env: [:])
|
|
||||||
// #expect(url == nil)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // @Test
|
|
||||||
// // func loadConfiguration() throws {
|
|
||||||
// // let configURL = Bundle.module.url(forResource: "config", withExtension: "json")!
|
|
||||||
// // let configData = try Data(contentsOf: configURL)
|
|
||||||
// // let decodedConfig = try JSONDecoder().decode(Configuration.self, from: configData)
|
|
||||||
// //
|
|
||||||
// // try withTestLogger(key: "loadConfiguration", logLevel: .debug) {
|
|
||||||
// // $0.fileClient = .liveValue
|
|
||||||
// // } operation: {
|
|
||||||
// // @Dependency(\.logger) var logger
|
|
||||||
// // let client = CliClient.live(env: ["HPA_CONFIG_FILE": path(for: configURL)])
|
|
||||||
// // let config = try client.loadConfiguration()
|
|
||||||
// // #expect(config == decodedConfig)
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
//
|
|
||||||
// @Test(arguments: ["config", "config.json"])
|
|
||||||
// func createConfiguration(filePath: String) throws {
|
|
||||||
// try withTestLogger(key: "createConfiguration", logLevel: .trace) {
|
|
||||||
// $0.fileClient = .liveValue
|
|
||||||
// } operation: {
|
|
||||||
// let client = CliClient.liveValue
|
|
||||||
// let tempDir = FileManager.default.temporaryDirectory
|
|
||||||
//
|
|
||||||
// let tempPath = path(for: tempDir.appending(path: filePath))
|
|
||||||
//
|
|
||||||
// try client.createConfiguration(path: tempPath, json: filePath.contains(".json"))
|
|
||||||
//
|
|
||||||
// #expect(FileManager.default.fileExists(atPath: tempPath))
|
|
||||||
//
|
|
||||||
// do {
|
|
||||||
// try client.createConfiguration(path: tempPath, json: true)
|
|
||||||
// #expect(Bool(false))
|
|
||||||
// } catch {
|
|
||||||
// #expect(Bool(true))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// try FileManager.default.removeItem(atPath: tempPath)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test
|
|
||||||
// func findVaultFile() throws {
|
|
||||||
// try withTestLogger(key: "findVaultFile", logLevel: .trace) {
|
|
||||||
// $0.fileClient = .liveValue
|
|
||||||
// } operation: {
|
|
||||||
// @Dependency(\.fileClient) var fileClient
|
|
||||||
// let vaultUrl = Bundle.module.url(forResource: "vault", withExtension: "yml")!
|
|
||||||
// let vaultDir = vaultUrl.deletingLastPathComponent()
|
|
||||||
// let url = try fileClient.findVaultFile(path(for: vaultDir))
|
|
||||||
// #expect(url == vaultUrl)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // @Test
|
|
||||||
// // func writeToml() throws {
|
|
||||||
// // let encoded: String = try TOMLEncoder().encode(Configuration.mock)
|
|
||||||
// // try encoded.write(to: URL(filePath: "hpa.toml"), atomically: true, encoding: .utf8)
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
@Suite("CliClientTests")
|
||||||
|
struct CliClientTests: TestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
func capturingClient() async throws {
|
||||||
|
let captured = CliClient.CapturingClient()
|
||||||
|
let client = CliClient.capturing(captured)
|
||||||
|
try await client.runCommand(quiet: false, shell: .zsh(), "foo", "bar")
|
||||||
|
|
||||||
|
let quiet = await captured.quiet!
|
||||||
|
#expect(quiet == false)
|
||||||
|
|
||||||
|
let shell = await captured.shell
|
||||||
|
#expect(shell == .zsh())
|
||||||
|
|
||||||
|
let arguments = await captured.arguments!
|
||||||
|
#expect(arguments == ["foo", "bar"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(arguments: ["encrypt", "decrypt"])
|
||||||
|
func runVault(argument: String) async throws {
|
||||||
|
let captured = CliClient.CapturingClient()
|
||||||
|
try await withMockConfiguration(captured, key: "runVault") {
|
||||||
|
$0.fileClient.findVaultFileInCurrentDirectory = { URL(filePath: "vault.yml") }
|
||||||
|
} operation: {
|
||||||
|
@Dependency(\.cliClient) var cliClient
|
||||||
|
let configuration = Configuration.mock
|
||||||
|
|
||||||
|
try await cliClient.runVaultCommand(.init(arguments: [argument], quiet: false, shell: nil))
|
||||||
|
|
||||||
|
let shell = await captured.shell
|
||||||
|
#expect(shell == .zsh(useDashC: true))
|
||||||
|
|
||||||
|
let vaultPath = URL(filePath: #file)
|
||||||
|
.deletingLastPathComponent()
|
||||||
|
.deletingLastPathComponent()
|
||||||
|
.appending(path: "vault.yml")
|
||||||
|
|
||||||
|
var encryptArgs: [String] = []
|
||||||
|
if argument == "encrypt", let id = configuration.vault.encryptId {
|
||||||
|
encryptArgs = ["--encrypt-vault-id", id]
|
||||||
|
}
|
||||||
|
|
||||||
|
let expectedArguments = [
|
||||||
|
"ansible-vault", argument
|
||||||
|
] + configuration.vault.args!
|
||||||
|
+ encryptArgs
|
||||||
|
+ [vaultPath.cleanFilePath]
|
||||||
|
|
||||||
|
let arguments = await captured.arguments
|
||||||
|
#expect(arguments == expectedArguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(arguments: [
|
||||||
|
Configuration(
|
||||||
|
args: ["--tags", "debug"],
|
||||||
|
useVaultArgs: true,
|
||||||
|
playbook: .init(directory: "playbook", inventory: nil),
|
||||||
|
vault: .mock
|
||||||
|
)
|
||||||
|
])
|
||||||
|
func runPlaybook(configuration: Configuration) async throws {
|
||||||
|
let captured = CliClient.CapturingClient()
|
||||||
|
try await withMockConfiguration(captured, configuration: configuration, key: "runPlaybook") {
|
||||||
|
@Dependency(\.cliClient) var cliClient
|
||||||
|
|
||||||
|
try await cliClient.runPlaybookCommand(.init(
|
||||||
|
arguments: [],
|
||||||
|
quiet: false,
|
||||||
|
shell: nil
|
||||||
|
))
|
||||||
|
|
||||||
|
let expectedArguments = [
|
||||||
|
"ansible-playbook", "playbook/main.yml",
|
||||||
|
"--inventory", "playbook/inventory.ini",
|
||||||
|
"--tags", "debug",
|
||||||
|
"--vault-id=myId@$SCRIPTS/vault-gopass-client"
|
||||||
|
]
|
||||||
|
|
||||||
|
let arguments = await captured.arguments
|
||||||
|
#expect(arguments == expectedArguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func withMockConfiguration(
|
||||||
|
_ capturing: CliClient.CapturingClient,
|
||||||
|
configuration: Configuration = .mock,
|
||||||
|
key: String,
|
||||||
|
logLevel: Logger.Level = .trace,
|
||||||
|
depednencies setupDependencies: @escaping (inout DependencyValues) -> Void = { _ in },
|
||||||
|
operation: @Sendable @escaping () async throws -> Void
|
||||||
|
) async rethrows {
|
||||||
|
try await withTestLogger(key: key, logLevel: logLevel) {
|
||||||
|
$0.configurationClient = .mock(configuration)
|
||||||
|
$0.cliClient = .capturing(capturing)
|
||||||
|
setupDependencies(&$0)
|
||||||
|
} operation: {
|
||||||
|
try await operation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ConfigurationClient {
|
||||||
|
static func mock(_ configuration: Configuration) -> Self {
|
||||||
|
var mock = Self.testValue
|
||||||
|
mock.find = { throw TestError() }
|
||||||
|
mock.load = { _ in configuration }
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestError: Error {}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"HPA_TEMPLATE_VERSION" : "main",
|
|
||||||
"HPA_TEMPLATE_DIR" : "/path/to/local/template",
|
|
||||||
"HPA_PLAYBOOK_DIR" : "/path/to/playbook",
|
|
||||||
"HPA_DEFAULT_VAULT_ARGS" : [
|
|
||||||
"--vault-id=myId@$SCRIPTS/vault-gopass-client"
|
|
||||||
],
|
|
||||||
"HPA_TEMPLATE_REPO" : "https://git.example.com/consult-template.git",
|
|
||||||
"HPA_DEFAULT_PLAYBOOK_ARGS" : [
|
|
||||||
"--tags",
|
|
||||||
"debug"
|
|
||||||
],
|
|
||||||
"HPA_DEFAULT_VAULT_ENCRYPT_ID" : "myId",
|
|
||||||
"HPA_DEFAULT_INVENTORY" : "/path/to/inventory.ini"
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"HPA_TEMPLATE_VERSION" : "main",
|
|
||||||
"HPA_TEMPLATE_DIR" : "/path/to/local/template",
|
|
||||||
"HPA_PLAYBOOK_DIR" : "/path/to/playbook",
|
|
||||||
"HPA_DEFAULT_VAULT_ARGS" : [
|
|
||||||
"--vault-id=myId@$SCRIPTS/vault-gopass-client"
|
|
||||||
],
|
|
||||||
"HPA_TEMPLATE_REPO" : "https://git.example.com/consult-template.git",
|
|
||||||
"HPA_DEFAULT_PLAYBOOK_ARGS" : [
|
|
||||||
"--tags",
|
|
||||||
"debug"
|
|
||||||
],
|
|
||||||
"HPA_DEFAULT_VAULT_ENCRYPT_ID" : "myId",
|
|
||||||
"HPA_DEFAULT_INVENTORY" : "/path/to/inventory.ini"
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"HPA_TEMPLATE_VERSION" : "main",
|
|
||||||
"HPA_TEMPLATE_DIR" : "/path/to/local/template",
|
|
||||||
"HPA_PLAYBOOK_DIR" : "/path/to/playbook",
|
|
||||||
"HPA_DEFAULT_VAULT_ARGS" : [
|
|
||||||
"--vault-id=myId@$SCRIPTS/vault-gopass-client"
|
|
||||||
],
|
|
||||||
"HPA_TEMPLATE_REPO" : "https://git.example.com/consult-template.git",
|
|
||||||
"HPA_DEFAULT_PLAYBOOK_ARGS" : [
|
|
||||||
"--tags",
|
|
||||||
"debug"
|
|
||||||
],
|
|
||||||
"HPA_DEFAULT_VAULT_ENCRYPT_ID" : "myId",
|
|
||||||
"HPA_DEFAULT_INVENTORY" : "/path/to/inventory.ini"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
---
|
|
||||||
# this is just here for testing, doesn't need to be encoded.
|
|
||||||
Reference in New Issue
Block a user