110 lines
3.0 KiB
Swift
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 {}
|