Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Worker architecture capability added #44

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2262,10 +2262,12 @@ let package = Package(
name: "WorkerCapabilities",
dependencies: [
.product(name: "AtomicModels", package: "CommandLineToolkit"),
.product(name: "DateProvider", package: "CommandLineToolkit"),
"EmceeLogging",
.product(name: "FileSystem", package: "CommandLineToolkit"),
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "PlistLib", package: "CommandLineToolkit"),
.product(name: "ProcessController", package: "CommandLineToolkit"),
"QueueModels",
.product(name: "Types", package: "CommandLineToolkit"),
"WorkerCapabilitiesModels",
Expand Down
1 change: 1 addition & 0 deletions Sources/EmceeLib/Commands/DistWorkCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public final class DistWorkCommand: Command {
OperatingSystemCapabilitiesProvider(
operatingSystemVersionProvider: ProcessInfo.processInfo
),
WorkerArchitectureCapabilitiesProvider(logger: logger)
]
),
for: WorkerCapabilitiesProvider.self
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// File.swift
//
//
// Created by a.smolianin on 15.07.2022.
//

import Foundation
import WorkerCapabilitiesModels
import ProcessController
import FileSystem
import DateProvider
import EmceeLogging

public final class WorkerArchitectureCapabilitiesProvider: WorkerCapabilitiesProvider {
private let logger: ContextualLogger
private let commandExecutor: CommandExecutor

public init(logger: ContextualLogger, commandExecutor: CommandExecutor) {
self.logger = logger
self.commandExecutor = commandExecutor
}

convenience public init(logger: ContextualLogger) {
self.init(logger: logger, commandExecutor: DefaultComandExecutor())
}

public func workerCapabilities() -> Set<WorkerCapability> {
return Set([WorkerCapability(name: WorkerCapabilityName("emcee.arch"), value: "\(getArch())")])
}

private func getArch() -> Arch {
var result = "\(Arch.unknown)"
do {
result = try commandExecutor.executeCommandWithOutput(env: [String: String](), arguments: ["/usr/sbin/sysctl", "-n", "machdep.cpu.brand_string"])
logger.info("Command \"sysctl -n machdep.cpu.brand_string\" = \(result)")
} catch {
logger.error("Command \"sysctl -n machdep.cpu.brand_string\" could not be completed. Error: \(error.localizedDescription)")
return .unknown
}
switch result {
case let arch where arch.contains(Arch.m1.rawValue):
return .m1
case let arch where arch.contains(Arch.x86.rawValue):
return .x86
default:
return .unknown
}
}

enum Arch: String {
case m1 = "Apple M1"
case x86 = "Intel"
case unknown //for m2 .etc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you want to expose CPU arch (x86_64, arm64), or CPU type, or CPU manufacturer? It seems currently these all are messed up a bit.

I assume it is more beneficial to have arch rather than manufacturer or kind (i.e. Core i5 or i7 or M1 or M2 Pro vs x86_64 and arm64). Could you please update your PR to expose architecture only?

}
}

public protocol CommandExecutor {
func executeCommandWithOutput(env: Dictionary<String,String>, arguments: [String]) throws -> String
}

extension CommandExecutor {
public func executeCommandWithOutput(env: Dictionary<String,String>, arguments: [String]) throws -> String {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to use ProcessControllerProvider to execute subcommands instead of adding another level of abstraction.
https://github.com/avito-tech/CommandLineToolkit/blob/master/Sources/ProcessController/ProcessControllerProvider.swift

let dateProvider = SystemDateProvider()
let filePropertiesProvider = FilePropertiesProviderImpl()
let controller = try DefaultProcessController(
dateProvider: dateProvider,
filePropertiesProvider: filePropertiesProvider,

subprocess: Subprocess(
arguments: arguments,
environment: Environment(env)
)
)

var stdoutData = Data()
controller.onStdout { _, data, _ in stdoutData.append(contentsOf: data) }

try controller.startAndListenUntilProcessDies()
guard let stdOut = String(data: stdoutData, encoding: .utf8) else {
return ""
}
return stdOut
}
}

class DefaultComandExecutor: CommandExecutor { }



Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// File.swift
//
//
// Created by a.smolianin on 25.08.2022.
//

import Foundation
import XCTest
import WorkerCapabilities
import WorkerCapabilitiesModels


class WorkerArchitectureCapabilitiesProviderTests: XCTestCase {
func test___x86_architecture() throws {
class IntelXeon: CommandExecutor {
func executeCommandWithOutput(env: Dictionary<String,String>, arguments: [String]) throws -> String {
return "Intel(R) Xeon(R) W-3245 CPU @ 3.20GHz"
}
}

let archProvider = WorkerArchitectureCapabilitiesProvider(logger: .noOp, commandExecutor: IntelXeon())
XCTAssertEqual(Set([WorkerCapability(name: WorkerCapabilityName("emcee.arch"), value: "x86")]), archProvider.workerCapabilities())
}

func test___m1_architecture() throws {
class M1: CommandExecutor {
func executeCommandWithOutput(env: Dictionary<String,String>, arguments: [String]) throws -> String {
return "Apple M1"
}
}

let archProvider = WorkerArchitectureCapabilitiesProvider(logger: .noOp, commandExecutor: M1())
XCTAssertEqual(Set([WorkerCapability(name: WorkerCapabilityName("emcee.arch"), value: "m1")]), archProvider.workerCapabilities())
}

func test___unknown_architecture() throws {
class Unknown: CommandExecutor {
func executeCommandWithOutput(env: Dictionary<String,String>, arguments: [String]) throws -> String {
return "Something unknown"
}
}

let archProvider = WorkerArchitectureCapabilitiesProvider(logger: .noOp, commandExecutor: Unknown())
XCTAssertEqual(Set([WorkerCapability(name: WorkerCapabilityName("emcee.arch"), value: "unknown")]), archProvider.workerCapabilities())
}
}