Files
swift-hpa/Sources/hpa/Helpers.swift
2024-11-29 14:30:52 -05:00

110 lines
3.0 KiB
Swift

import ArgumentParser
import CliClient
import Dependencies
import Foundation
import Logging
import Rainbow
import ShellClient
extension CommandConfiguration {
static func playbookCommandConfiguration(commandName: String, abstract: String) -> Self {
Self(
commandName: commandName,
abstract: "\(abstract.blue)",
discussion: """
\("IMPORTANT NOTE:".red) Any extra arguments to pass to the playbook invocation have to
be at the end with `--` before any arguments otherwise there will
be an "Unkown option" error.
\("Example of passing extra args to the playbook:".yellow)
$ hpa \(commandName) /my/project -- --vault-id "myId@$SCRIPTS/vault-gopass-client"
\("See Also:".yellow)
You can run the following command to see the options that can be passed to the playbook
invocation.
$ ansible-playbook --help
"""
)
}
}
func ensureString(
globals: GlobalOptions,
configuration: Configuration,
globalsKeyPath: KeyPath<GlobalOptions, String?>,
configurationKeyPath: KeyPath<Configuration, String?>
) throws -> String {
if let global = globals[keyPath: globalsKeyPath] {
return global
}
guard let configuration = configuration[keyPath: configurationKeyPath] else {
throw PlaybookNotFound()
}
return configuration
}
func runPlaybook(
commandName: String,
globals: GlobalOptions,
args: [String]
) async throws {
try await withDependencies {
$0.logger = .init(label: "\("hpa".yellow)")
switch globals.verbose {
case 0:
$0.logger.logLevel = .info
case 1:
$0.logger.logLevel = .debug
case 2:
$0.logger.logLevel = .trace
default:
$0.logger.logLevel = .info
}
$0.logger[metadataKey: "command"] = "\(commandName.blue)"
} operation: {
@Dependency(\.cliClient) var cliClient
@Dependency(\.logger) var logger
@Dependency(\.asyncShellClient) var shellClient
logger.debug("Begin run playbook: \(globals)")
let configuration = try cliClient.loadConfiguration()
logger.debug("Loaded configuration: \(configuration)")
let playbookDir = try ensureString(
globals: globals,
configuration: configuration,
globalsKeyPath: \.playbookDir,
configurationKeyPath: \.playbookDir
)
let playbook = "\(playbookDir)/main.yml"
let inventory = (try? ensureString(
globals: globals,
configuration: configuration,
globalsKeyPath: \.inventoryPath,
configurationKeyPath: \.inventoryPath
)) ?? "\(playbookDir)/inventory.ini"
var playbookArgs = [
"ansible-playbook", playbook,
"--inventory", inventory
] + args
if let defaultArgs = configuration.defaultPlaybookArgs {
playbookArgs.append(defaultArgs)
}
try await shellClient.foreground(.init(
shell: .zsh(useDashC: true),
environment: ProcessInfo.processInfo.environment,
in: nil,
playbookArgs
))
}
}
struct PlaybookNotFound: Error {}