feat: Begins vault commands, adds nodes for rendering discussion documentation.
This commit is contained in:
@@ -17,6 +17,7 @@ public struct CliClient: Sendable {
|
||||
public var loadConfiguration: @Sendable () throws -> Configuration
|
||||
public var runCommand: @Sendable ([String], Bool, ShellCommand.Shell) async throws -> Void
|
||||
public var createConfiguration: @Sendable (_ path: String, _ json: Bool) throws -> Void
|
||||
public var findVaultFileInCurrentDirectory: @Sendable () throws -> String
|
||||
|
||||
public func runCommand(
|
||||
quiet: Bool,
|
||||
@@ -95,6 +96,11 @@ extension CliClient: DependencyKey {
|
||||
}
|
||||
|
||||
try fileClient.write(path, data)
|
||||
} findVaultFileInCurrentDirectory: {
|
||||
guard let url = try fileClient.findVaultFileInCurrentDirectory() else {
|
||||
throw CliClientError.vaultFileNotFound
|
||||
}
|
||||
return path(for: url)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +113,7 @@ extension CliClient: DependencyKey {
|
||||
|
||||
enum CliClientError: Error {
|
||||
case fileExistsAtPath(String)
|
||||
case vaultFileNotFound
|
||||
}
|
||||
|
||||
private let jsonEncoder: JSONEncoder = {
|
||||
|
||||
@@ -3,7 +3,7 @@ import Foundation
|
||||
import ShellClient
|
||||
|
||||
/// Represents the configuration.
|
||||
public struct Configuration: Codable {
|
||||
public struct Configuration: Codable, Sendable {
|
||||
|
||||
public let playbookDir: String?
|
||||
public let inventoryPath: String?
|
||||
@@ -11,6 +11,7 @@ public struct Configuration: Codable {
|
||||
public let templateRepoVersion: String?
|
||||
public let templateDir: String?
|
||||
public let defaultPlaybookArgs: [String]?
|
||||
public let defaultVaultArgs: [String]?
|
||||
|
||||
fileprivate enum CodingKeys: String, CodingKey {
|
||||
case playbookDir = "HPA_PLAYBOOK_DIR"
|
||||
@@ -19,6 +20,7 @@ public struct Configuration: Codable {
|
||||
case templateRepoVersion = "HPA_TEMPLATE_VERSION"
|
||||
case templateDir = "HPA_TEMPLATE_DIR"
|
||||
case defaultPlaybookArgs = "HPA_DEFAULT_PLAYBOOK_ARGS"
|
||||
case defaultVaultArgs = "HPA_DEFAULT_VAULT_ARGS"
|
||||
}
|
||||
|
||||
public static func fromEnv(
|
||||
@@ -31,16 +33,14 @@ public struct Configuration: Codable {
|
||||
let hpaValues: [String: String] = env.filter { $0.key.contains("HPA") }
|
||||
logger.debug("HPA env vars: \(hpaValues)")
|
||||
|
||||
let defaultArgs: [String]? = hpaValues.value(key: .defaultPlaybookArgs)
|
||||
.flatMap { $0.split(separator: ",").map(String.init) }
|
||||
|
||||
return Configuration(
|
||||
playbookDir: hpaValues.value(key: .playbookDir),
|
||||
inventoryPath: hpaValues.value(key: .inventoryPath),
|
||||
templateRepo: hpaValues.value(key: .templateRepo),
|
||||
templateRepoVersion: hpaValues.value(key: .templateRepoVersion),
|
||||
templateDir: hpaValues.value(key: .templateDir),
|
||||
defaultPlaybookArgs: defaultArgs
|
||||
playbookDir: hpaValues.value(for: .playbookDir),
|
||||
inventoryPath: hpaValues.value(for: .inventoryPath),
|
||||
templateRepo: hpaValues.value(for: .templateRepo),
|
||||
templateRepoVersion: hpaValues.value(for: .templateRepoVersion),
|
||||
templateDir: hpaValues.value(for: .templateDir),
|
||||
defaultPlaybookArgs: hpaValues.array(for: .defaultPlaybookArgs),
|
||||
defaultVaultArgs: hpaValues.array(for: .defaultVaultArgs)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ public struct Configuration: Codable {
|
||||
templateRepo: "https://git.example.com/consult-template.git",
|
||||
templateRepoVersion: "main",
|
||||
templateDir: "/path/to/local/template",
|
||||
defaultPlaybookArgs: ["--vault-id=myId@$SCRIPTS/vault-gopass-client"]
|
||||
defaultPlaybookArgs: ["--tags", "debug"],
|
||||
defaultVaultArgs: ["--vault-id=myId@$SCRIPTS/vault-gopass-client"]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -82,7 +83,11 @@ public struct Configuration: Codable {
|
||||
}
|
||||
|
||||
extension [String: String] {
|
||||
fileprivate func value(key codingKey: Configuration.CodingKeys) -> String? {
|
||||
fileprivate func value(for codingKey: Configuration.CodingKeys) -> String? {
|
||||
self[codingKey.rawValue]
|
||||
}
|
||||
|
||||
fileprivate func array(for codingKey: Configuration.CodingKeys) -> [String]? {
|
||||
value(for: codingKey).flatMap { $0.split(separator: ",").map(String.init) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ public struct FileClient: Sendable {
|
||||
public var isDirectory: @Sendable (URL) -> Bool = { _ in false }
|
||||
public var isReadable: @Sendable (URL) -> Bool = { _ in false }
|
||||
public var fileExists: @Sendable (String) -> Bool = { _ in false }
|
||||
public var findVaultFileInCurrentDirectory: @Sendable () throws -> URL?
|
||||
public var write: @Sendable (String, Data) throws -> Void
|
||||
}
|
||||
|
||||
@@ -33,6 +34,7 @@ extension FileClient: DependencyKey {
|
||||
isDirectory: { client.isDirectory(url: $0) },
|
||||
isReadable: { client.isReadable(url: $0) },
|
||||
fileExists: { client.fileExists(at: $0) },
|
||||
findVaultFileInCurrentDirectory: { try client.findVaultFileInCurrentDirectory() },
|
||||
write: { path, data in
|
||||
try data.write(to: URL(filePath: path))
|
||||
}
|
||||
@@ -66,6 +68,31 @@ private struct LiveFileClient: @unchecked Sendable {
|
||||
fileManager.fileExists(atPath: path)
|
||||
}
|
||||
|
||||
func findVaultFileInCurrentDirectory() throws -> URL? {
|
||||
let urls = try fileManager.contentsOfDirectory(at: URL(filePath: "."), includingPropertiesForKeys: nil)
|
||||
|
||||
if let vault = urls.firstVaultFile {
|
||||
return vault
|
||||
}
|
||||
|
||||
// check for folders that end with "vars" and search those next.
|
||||
for folder in urls.filter({ $0.absoluteString.hasSuffix("vars/") }) {
|
||||
let files = try fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil)
|
||||
if let vault = files.firstVaultFile {
|
||||
return vault
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to check all sub-folders
|
||||
for folder in urls.filter({ self.isDirectory(url: $0) && !$0.absoluteString.hasSuffix("vars/") }) {
|
||||
let files = try fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil)
|
||||
if let vault = files.firstVaultFile {
|
||||
return vault
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadFile(at url: URL, into env: inout [String: String], decoder: JSONDecoder) throws {
|
||||
@Dependency(\.logger) var logger
|
||||
logger.trace("Begin load file for: \(path(for: url))")
|
||||
@@ -101,3 +128,9 @@ private struct LiveFileClient: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension Array where Element == URL {
|
||||
var firstVaultFile: URL? {
|
||||
first { $0.absoluteString.hasSuffix("vault.yml") }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user