Skip to content

Commit

Permalink
Deploy queue server config with launchd plist
Browse files Browse the repository at this point in the history
  • Loading branch information
Timofey Solonin committed Dec 20, 2021
1 parent 23fbcc0 commit 8ae720e
Show file tree
Hide file tree
Showing 12 changed files with 91 additions and 56 deletions.
16 changes: 14 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ let package = Package(
.product(name: "LaunchdUtils", package: "CommandLineToolkit"),
.product(name: "PathLib", package: "CommandLineToolkit"),
"QueueModels",
"QueueServerConfiguration",
"SSHDeployer",
.product(name: "SocketModels", package: "CommandLineToolkit"),
.product(name: "Tmp", package: "CommandLineToolkit"),
Expand Down Expand Up @@ -541,6 +542,7 @@ let package = Package(
"QueueCommunication",
"QueueModels",
"QueueServer",
"QueueServerConfiguration",
"QueueServerPortProvider",
"RESTMethods",
"RESTServer",
Expand Down Expand Up @@ -782,8 +784,6 @@ let package = Package(
"FileLock",
.product(name: "FileSystem", package: "CommandLineToolkit"),
"LocalHostDeterminer",
"LoggingSetup",
"MetricsExtensions",
"QueueCommunication",
"QueueModels",
"QueueServer",
Expand Down Expand Up @@ -1168,6 +1168,18 @@ let package = Package(
],
path: "Sources/QueueServer"
),
.target(
name: "QueueServerConfiguration",
dependencies: [
"AutomaticTermination",
"Deployer",
"DistWorkerModels",
"LoggingSetup",
"MetricsExtensions",
"QueueModels",
],
path: "Sources/QueueServerConfiguration"
),
.target(
name: "QueueServerPortProvider",
dependencies: [
Expand Down
41 changes: 14 additions & 27 deletions Sources/DistDeployer/RemoteQueueLaunchdPlist.swift
Original file line number Diff line number Diff line change
@@ -1,51 +1,38 @@
import Deployer
import Foundation
import LaunchdUtils
import PathLib
import QueueModels
import SSHDeployer
import Tmp

public final class RemoteQueueLaunchdPlist {
/// Unique deployment id
private let deploymentId: String
/// Deployment destination where queue should start
private let deploymentDestination: DeploymentDestination
/// Emcee binary version
private let emceeVersion: Version
/// Queue server executable
private let queueServerBinaryDeployableItem: DeployableItem
/// A JSON file location that contains QueueServerConfiguration for queue server
private let queueServerConfigurationLocation: QueueServerConfigurationLocation
/// Path to QueueServerConfiguration JSON at the deployment location
private let queueServerConfigurationPath: AbsolutePath
/// Path to the working directory of an Emcee binary at the deployment location
private let containerPath: AbsolutePath
/// Path to the Emcee binary at the deployment location
private let remoteQueueServerBinaryPath: AbsolutePath

public init(
deploymentId: String,
deploymentDestination: DeploymentDestination,
emceeDeployableItem: DeployableItem,
emceeVersion: Version,
queueServerConfigurationLocation: QueueServerConfigurationLocation
queueServerConfigurationPath: AbsolutePath,
containerPath: AbsolutePath,
remoteQueueServerBinaryPath: AbsolutePath
) {
self.deploymentId = deploymentId
self.deploymentDestination = deploymentDestination
self.emceeVersion = emceeVersion
self.queueServerBinaryDeployableItem = emceeDeployableItem
self.queueServerConfigurationLocation = queueServerConfigurationLocation
self.queueServerConfigurationPath = queueServerConfigurationPath
self.containerPath = containerPath
self.remoteQueueServerBinaryPath = remoteQueueServerBinaryPath
}

public func plistData() throws -> Data {
let containerPath = SSHDeployer.remoteContainerPath(
forDeployable: queueServerBinaryDeployableItem,
destination: deploymentDestination,
deploymentId: deploymentId
)
let remoteQueueServerBinaryPath = SSHDeployer.remotePath(
deployable: queueServerBinaryDeployableItem,
file: try DeployableItemSingleFileExtractor(
deployableItem: queueServerBinaryDeployableItem
).singleDeployableFile(),
destination: deploymentDestination,
deploymentId: deploymentId
)

let jobLabel = "ru.avito.emcee.queueServer.\(deploymentId.removingWhitespaces())"

let launchdPlist = LaunchdPlist(
Expand All @@ -56,7 +43,7 @@ public final class RemoteQueueLaunchdPlist {
programArguments: [
remoteQueueServerBinaryPath.pathString, "startLocalQueueServer",
"--emcee-version", emceeVersion.value,
"--queue-server-configuration-location", try queueServerConfigurationLocation.resourceLocation.stringValue()
"--queue-server-configuration-location", queueServerConfigurationPath.pathString,
],
environmentVariables: [:],
workingDirectory: containerPath.pathString,
Expand Down
51 changes: 44 additions & 7 deletions Sources/DistDeployer/RemoteQueueStarter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import FileSystem
import Foundation
import PathLib
import QueueModels
import QueueServerConfiguration
import SSHDeployer
import Tmp
import UniqueIdentifierGenerator
import Zip
Expand All @@ -14,7 +16,7 @@ public final class RemoteQueueStarter {
private let emceeVersion: Version
private let fileSystem: FileSystem
private let logger: ContextualLogger
private let queueServerConfigurationLocation: QueueServerConfigurationLocation
private let queueServerConfiguration: QueueServerConfiguration
private let tempFolder: TemporaryFolder
private let uniqueIdentifierGenerator: UniqueIdentifierGenerator
private let zipCompressor: ZipCompressor
Expand All @@ -25,7 +27,7 @@ public final class RemoteQueueStarter {
emceeVersion: Version,
fileSystem: FileSystem,
logger: ContextualLogger,
queueServerConfigurationLocation: QueueServerConfigurationLocation,
queueServerConfiguration: QueueServerConfiguration,
tempFolder: TemporaryFolder,
uniqueIdentifierGenerator: UniqueIdentifierGenerator,
zipCompressor: ZipCompressor
Expand All @@ -35,7 +37,7 @@ public final class RemoteQueueStarter {
self.emceeVersion = emceeVersion
self.fileSystem = fileSystem
self.logger = logger
self.queueServerConfigurationLocation = queueServerConfigurationLocation
self.queueServerConfiguration = queueServerConfiguration
self.tempFolder = tempFolder
self.uniqueIdentifierGenerator = uniqueIdentifierGenerator
self.zipCompressor = zipCompressor
Expand All @@ -56,13 +58,45 @@ public final class RemoteQueueStarter {
deployableItems: [DeployableItem],
emceeBinaryDeployableItem: DeployableItem
) throws {
let containerPath = SSHDeployer.remoteContainerPath(
forDeployable: emceeBinaryDeployableItem,
destination: deploymentDestination,
deploymentId: deploymentId
)
let remoteQueueServerBinaryPath = SSHDeployer.remotePath(
deployable: emceeBinaryDeployableItem,
file: try DeployableItemSingleFileExtractor(
deployableItem: emceeBinaryDeployableItem
).singleDeployableFile(),
destination: deploymentDestination,
deploymentId: deploymentId
)

let queueServerConfigurationTargetPath = "queue_server_configuration.json"
let queueServerConfigurationDirectory = "queue_server_configuration"
let queueServerConfigurationDeployableItem = DeployableItem(
name: queueServerConfigurationDirectory,
files: [
DeployableFile(
source: try tempFolder.createFile(
filename: queueServerConfigurationTargetPath,
contents: JSONEncoder().encode(queueServerConfiguration)
),
destination: RelativePath(queueServerConfigurationTargetPath)
)
]
)

let launchdPlistTargetPath = "queue_server_launchd.plist"
let launchdPlist = RemoteQueueLaunchdPlist(
deploymentId: deploymentId,
deploymentDestination: deploymentDestination,
emceeDeployableItem: emceeBinaryDeployableItem,
emceeVersion: emceeVersion,
queueServerConfigurationLocation: queueServerConfigurationLocation
queueServerConfigurationPath: containerPath.removingLastComponent.appending(
queueServerConfigurationDirectory,
queueServerConfigurationTargetPath
),
containerPath: containerPath,
remoteQueueServerBinaryPath: remoteQueueServerBinaryPath
)
let launchdPlistDeployableItem = DeployableItem(
name: "queue_server_launchd_plist",
Expand All @@ -84,7 +118,10 @@ public final class RemoteQueueStarter {
let deployer = DistDeployer(
deploymentId: deploymentId,
deploymentDestination: deploymentDestination,
deployableItems: deployableItems + [launchdPlistDeployableItem],
deployableItems: deployableItems + [
launchdPlistDeployableItem,
queueServerConfigurationDeployableItem
],
deployableCommands: [
launchctlDeployableCommands.forceUnloadFromBackgroundCommand(),
launchctlDeployableCommands.forceLoadInBackgroundCommand()
Expand Down
1 change: 1 addition & 0 deletions Sources/EmceeLib/Arguments/ArgumentsReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import DistDeployer
import EmceeExtensions
import Foundation
import LocalQueueServerRunner
import QueueServerConfiguration
import ResourceLocationResolver
import TestArgFile
import TestDiscovery
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import LocalQueueServerRunner
import MetricsExtensions
import PathLib
import QueueModels
import QueueServerConfiguration
import SocketModels

public final class InitQueueServerConfigCommand: Command {
Expand Down
11 changes: 6 additions & 5 deletions Sources/EmceeLib/Commands/RunTestsOnRemoteQueueCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import QueueClient
import QueueCommunication
import QueueModels
import QueueServer
import QueueServerConfiguration
import RESTServer
import RemotePortDeterminer
import RequestSender
Expand Down Expand Up @@ -91,7 +92,7 @@ public final class RunTestsOnRemoteQueueCommand: Command {
let runningQueueServerAddress = try detectRemotelyRunningQueueServerPortsOrStartRemoteQueueIfNeeded(
emceeVersion: emceeVersion,
queueServerDeploymentDestinations: queueServerConfiguration.queueServerDeploymentDestinations,
queueServerConfigurationLocation: queueServerConfigurationLocation,
queueServerConfiguration: queueServerConfiguration,
logger: logger
)

Expand Down Expand Up @@ -184,7 +185,7 @@ public final class RunTestsOnRemoteQueueCommand: Command {
private func detectRemotelyRunningQueueServerPortsOrStartRemoteQueueIfNeeded(
emceeVersion: Version,
queueServerDeploymentDestinations: [DeploymentDestination],
queueServerConfigurationLocation: QueueServerConfigurationLocation,
queueServerConfiguration: QueueServerConfiguration,
logger: ContextualLogger
) throws -> SocketAddress {
logger.info("Searching for queue server on '\(queueServerDeploymentDestinations.map(\.host))' with queue version \(emceeVersion)")
Expand All @@ -207,7 +208,7 @@ public final class RunTestsOnRemoteQueueCommand: Command {
try startNewInstanceOfRemoteQueueServer(
queueServerDeploymentDestinations: queueServerDeploymentDestinations,
emceeVersion: emceeVersion,
queueServerConfigurationLocation: queueServerConfigurationLocation,
queueServerConfiguration: queueServerConfiguration,
logger: logger
)

Expand All @@ -224,7 +225,7 @@ public final class RunTestsOnRemoteQueueCommand: Command {
private func startNewInstanceOfRemoteQueueServer(
queueServerDeploymentDestinations: [DeploymentDestination],
emceeVersion: Version,
queueServerConfigurationLocation: QueueServerConfigurationLocation,
queueServerConfiguration: QueueServerConfiguration,
logger: ContextualLogger
) throws {
logger.info("No running queue server has been found. Will deploy and start remote queue.")
Expand All @@ -238,7 +239,7 @@ public final class RunTestsOnRemoteQueueCommand: Command {
emceeVersion: emceeVersion,
fileSystem: try di.get(),
logger: logger,
queueServerConfigurationLocation: queueServerConfigurationLocation,
queueServerConfiguration: queueServerConfiguration,
tempFolder: try di.get(),
uniqueIdentifierGenerator: try di.get(),
zipCompressor: try di.get()
Expand Down
1 change: 1 addition & 0 deletions Sources/EmceeLib/Commands/StartQueueServerCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ProcessController
import QueueCommunication
import QueueModels
import QueueServer
import QueueServerConfiguration
import QueueServerPortProvider
import RemotePortDeterminer
import RequestSender
Expand Down
24 changes: 9 additions & 15 deletions Tests/DistDeployerTests/RemoteQueueLaunchdPlistTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,16 @@ import QueueModels
import XCTest

final class RemoteQueueLaunchdPlistTests: XCTestCase {
let remoteConfigUrl = URL(string: "http://example.com/file.zip#config.json")!
let queueServerConfigurationPath: AbsolutePath = "/path/to/queueServerConfiguration.json"
let containerPath: AbsolutePath = "/path/to/container"
let remoteQueueServerBinaryPath: AbsolutePath = "/path/to/remoteQueueServerBinary"
let emceeVersion: Version = "emceeVersion"
lazy var launchdPlist = RemoteQueueLaunchdPlist(
deploymentId: "deploymentId",
deploymentDestination: DeploymentDestinationFixtures().build(),
emceeDeployableItem: DeployableItem(
name: "emcee",
files: [
DeployableFile(
source: AbsolutePath("local_file"),
destination: RelativePath("remote_filename")
)
]
),
emceeVersion: emceeVersion,
queueServerConfigurationLocation: QueueServerConfigurationLocation(.remoteUrl(remoteConfigUrl, [:]))
queueServerConfigurationPath: self.queueServerConfigurationPath,
containerPath: self.containerPath,
remoteQueueServerBinaryPath: self.remoteQueueServerBinaryPath
)

func test() throws {
Expand All @@ -35,15 +29,15 @@ final class RemoteQueueLaunchdPlistTests: XCTestCase {
XCTAssertEqual(
decodedDict["ProgramArguments"] as? Array,
[
"/Users/username/path/deploymentId/emcee/remote_filename",
"/path/to/remoteQueueServerBinary",
"startLocalQueueServer",
"--emcee-version", emceeVersion.value,
"--queue-server-configuration-location", remoteConfigUrl.absoluteString
"--queue-server-configuration-location", "/path/to/queueServerConfiguration.json"
]
)
XCTAssertEqual(
decodedDict["WorkingDirectory"] as? String,
"/Users/username/path/deploymentId/emcee"
"/path/to/container"
)
XCTAssertEqual(
decodedDict["Disabled"] as? Bool,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import LocalQueueServerRunner
import MetricsExtensions
import LoggingSetup
import QueueModels
import QueueServerConfiguration
import SocketModels
import TestHelpers
import XCTest
Expand Down

0 comments on commit 8ae720e

Please sign in to comment.