217 lines
6.4 KiB
Swift
217 lines
6.4 KiB
Swift
import ConfigurationClient
|
|
import Dependencies
|
|
import Foundation
|
|
import PlaybookClient
|
|
|
|
extension CliClient.RunPlaybook {
|
|
|
|
static func makeCommonArguments(
|
|
configuration: Configuration,
|
|
inventoryFilePath: String?
|
|
) async throws -> [String] {
|
|
@Dependency(\.logger) var logger
|
|
@Dependency(\.playbookClient) var playbookClient
|
|
|
|
let playbookDirectory = try await playbookClient.repository.directory(configuration)
|
|
let playbookPath = "\(playbookDirectory)/\(Constants.playbookFileName)"
|
|
logger.trace("Playbook path: \(playbookPath)")
|
|
|
|
let inventoryPath = ensuredInventoryPath(
|
|
inventoryFilePath,
|
|
configuration: configuration,
|
|
playbookDirectory: playbookDirectory
|
|
)
|
|
logger.trace("Inventory path: \(inventoryPath)")
|
|
|
|
var arguments = [
|
|
Constants.playbookCommand, playbookPath,
|
|
"--inventory", inventoryPath
|
|
]
|
|
|
|
if let defaultArgs = configuration.args {
|
|
arguments.append(contentsOf: defaultArgs)
|
|
}
|
|
|
|
if configuration.useVaultArgs, let vaultArgs = configuration.vault.args {
|
|
arguments.append(contentsOf: vaultArgs)
|
|
}
|
|
|
|
logger.trace("Common arguments: \(inventoryPath)")
|
|
return arguments
|
|
}
|
|
|
|
}
|
|
|
|
extension CliClient.RunPlaybook.BuildOptions {
|
|
private func applyArguments(
|
|
to arguments: inout [String],
|
|
configuration: Configuration
|
|
) throws {
|
|
let projectDirectory = projectDirectory
|
|
?? ProcessInfo.processInfo.environment["PWD"]
|
|
|
|
guard let projectDirectory else {
|
|
throw CliClientError.projectDirectoryNotFound
|
|
}
|
|
|
|
arguments.append(contentsOf: [
|
|
"--tags", "build-project",
|
|
"--extra-vars", "project_dir=\(projectDirectory)"
|
|
])
|
|
|
|
if let extraOptions = extraOptions {
|
|
arguments.append(contentsOf: extraOptions)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension CliClient.RunPlaybook.CreateOptions {
|
|
private func applyArguments(
|
|
to arguments: inout [String],
|
|
configuration: Configuration
|
|
) throws {
|
|
let json = try createJSONData(configuration: configuration)
|
|
|
|
arguments.append(contentsOf: [
|
|
"--tags", "setup-project",
|
|
"--extra-vars", "project_dir=\(projectDirectory)",
|
|
"--extra-vars", "'\(json)'"
|
|
])
|
|
|
|
if let extraOptions {
|
|
arguments.append(contentsOf: extraOptions)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension CliClient.PlaybookOptions.Route {
|
|
|
|
private func parseInventoryPath(
|
|
_ configuration: Configuration,
|
|
_ playbookDirectory: String
|
|
) -> String {
|
|
let inventoryFilePath: String?
|
|
|
|
switch self {
|
|
case let .build(options):
|
|
inventoryFilePath = options.inventoryFilePath
|
|
case let .create(options):
|
|
inventoryFilePath = options.inventoryFilePath
|
|
}
|
|
|
|
return ensuredInventoryPath(
|
|
inventoryFilePath,
|
|
configuration: configuration,
|
|
playbookDirectory: playbookDirectory
|
|
)
|
|
}
|
|
|
|
func makeArguments(configuration: Configuration) async throws -> [String] {
|
|
@Dependency(\.logger) var logger
|
|
@Dependency(\.playbookClient) var playbookClient
|
|
|
|
let playbookDirectory = try await playbookClient.repository.directory(configuration)
|
|
let playbookPath = "\(playbookDirectory)/\(Constants.playbookFileName)"
|
|
logger.trace("Playbook path: \(playbookPath)")
|
|
|
|
let inventoryPath = parseInventoryPath(configuration, playbookDirectory)
|
|
logger.trace("Inventory path: \(inventoryPath)")
|
|
|
|
var arguments = [
|
|
Constants.playbookCommand, playbookPath,
|
|
"--inventory", inventoryPath
|
|
]
|
|
|
|
if let defaultArgs = configuration.args {
|
|
arguments.append(contentsOf: defaultArgs)
|
|
}
|
|
|
|
if configuration.useVaultArgs, let vaultArgs = configuration.vault.args {
|
|
arguments.append(contentsOf: vaultArgs)
|
|
}
|
|
|
|
// try applyArguments(to: &arguments, configuration: configuration)
|
|
|
|
return arguments
|
|
}
|
|
}
|
|
|
|
// NOTE: We're not using the `Coders` client because we generally do not
|
|
// want the output to be `prettyPrinted` or anything, unless we're running
|
|
// tests, so we use a supplied json encoder.
|
|
|
|
extension CliClient.RunPlaybook.CreateOptions {
|
|
|
|
func createJSONData(
|
|
configuration: Configuration,
|
|
encoder: JSONEncoder = .init()
|
|
) throws -> Data {
|
|
@Dependency(\.logger) var logger
|
|
|
|
let templateDir = template.directory ?? configuration.template.directory
|
|
let templateRepo = template.url ?? configuration.template.url
|
|
let version = template.version ?? configuration.template.version
|
|
|
|
logger.debug("""
|
|
(\(useLocalTemplateDirectory), \(String(describing: templateDir)), \(String(describing: templateRepo)))
|
|
""")
|
|
|
|
switch (useLocalTemplateDirectory, templateDir, templateRepo) {
|
|
case (true, .none, _):
|
|
// User supplied they wanted to use a local template directory, but we could not find
|
|
// the path set from command line or in configuration.
|
|
throw CliClientError.templateDirectoryNotFound
|
|
case let (false, _, .some(repo)):
|
|
// User did not supply they wanted to use a local template directory, and we found a repo url that was
|
|
// either set by the command line or found in the configuration.
|
|
logger.debug("Using repo.")
|
|
return try encoder.encode(TemplateRepo(repo: repo, version: version))
|
|
case let (true, .some(templateDir), _):
|
|
// User supplied they wanted to use a local template directory, and we found the template directory
|
|
// either set by the command line or in the configuration.
|
|
logger.debug("Using template directory.")
|
|
return try encoder.encode(TemplateDirJson(path: templateDir))
|
|
case let (false, .some(templateDir), _):
|
|
// User supplied they did not wanted to use a local template directory, and we found the template directory
|
|
// either set by the command line or in the configuration, and no repo was found / handled previously.
|
|
logger.debug("Using template directory.")
|
|
return try encoder.encode(TemplateDirJson(path: templateDir))
|
|
case (_, .none, .none):
|
|
// We could not find a repo or template directory.
|
|
throw CliClientError.templateDirectoryOrRepoNotSpecified
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct TemplateDirJson: Encodable {
|
|
|
|
let template: Template
|
|
|
|
init(path: String) {
|
|
self.template = .init(path: path)
|
|
}
|
|
|
|
struct Template: Encodable {
|
|
let path: String
|
|
}
|
|
}
|
|
|
|
private struct TemplateRepo: Encodable {
|
|
|
|
let template: Template
|
|
|
|
init(repo: String, version: String?) {
|
|
self.template = .init(repo: .init(url: repo, version: version ?? "main"))
|
|
}
|
|
|
|
struct Template: Encodable {
|
|
let repo: Repo
|
|
}
|
|
|
|
struct Repo: Encodable {
|
|
let url: String
|
|
let version: String
|
|
}
|
|
}
|