From 864afad2b353333970aba509fd6ebea5ee23158e Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Tue, 14 Jan 2025 14:07:56 -0600 Subject: [PATCH] adds a test that illustrates #55 - env not getting set on remote execution with stream --- Package.resolved | 28 +++++----- Tests/CitadelTests/Citadel2Tests.swift | 74 ++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/Package.resolved b/Package.resolved index fde8e45..baa8214 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/attaswift/BigInt.git", "state": { "branch": null, - "revision": "0ed110f7555c34ff468e72e1686e59721f2b0da6", - "version": "5.3.0" + "revision": "114343a705df4725dfe7ab8a2a326b8883cfd79c", + "version": "5.5.1" } }, { @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/mtynior/ColorizeSwift.git", "state": { "branch": null, - "revision": "2a354639173d021f4648cf1912b2b00a3a7cd83c", - "version": "1.6.0" + "revision": "4e7daa138510b77a3cce9f6a31a116f8536347dd", + "version": "1.7.0" } }, { @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/apple/swift-collections.git", "state": { "branch": null, - "revision": "94cf62b3ba8d4bed62680a282d4c25f9c63c2efb", - "version": "1.1.0" + "revision": "671108c96644956dddcd89dd59c203dcdb36cec7", + "version": "1.1.4" } }, { @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/apple/swift-log.git", "state": { "branch": null, - "revision": "e97a6fcb1ab07462881ac165fdbb37f067e205d5", - "version": "1.5.4" + "revision": "96a2f8a0fa41e9e09af4585e2724c4e825410b91", + "version": "1.6.2" } }, { @@ -60,8 +60,8 @@ "repositoryURL": "https://github.com/apple/swift-nio.git", "state": { "branch": null, - "revision": "359c461e5561d22c6334828806cc25d759ca7aa6", - "version": "2.65.0" + "revision": "27c839f4700069928196cd0e9fa03b22f297078a", + "version": "2.78.0" } }, { @@ -69,8 +69,8 @@ "repositoryURL": "https://github.com/Joannis/swift-nio-ssh.git", "state": { "branch": null, - "revision": "01e03b888734b03f1005b0ca329d7b5af50208e7", - "version": "0.3.2" + "revision": "0b3992e7acfdbf765aecd5e20bd8831d33d42453", + "version": "0.3.3" } }, { @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/apple/swift-system.git", "state": { "branch": null, - "revision": "025bcb1165deab2e20d4eaba79967ce73013f496", - "version": "1.2.1" + "revision": "c8a44d836fe7913603e246acab7c528c2e780168", + "version": "1.4.0" } } ] diff --git a/Tests/CitadelTests/Citadel2Tests.swift b/Tests/CitadelTests/Citadel2Tests.swift index 8c077ec..63a3396 100644 --- a/Tests/CitadelTests/Citadel2Tests.swift +++ b/Tests/CitadelTests/Citadel2Tests.swift @@ -333,4 +333,78 @@ final class Citadel2Tests: XCTestCase { try await client.close() } + + func testEnvCommandStreamToOpenSSHServer() async throws { + guard + let host = ProcessInfo.processInfo.environment["SSH_HOST"] else { + throw XCTSkip("MISSING ENVIRONMENT VARIABLES - SSH_HOST") + } + guard + let _port = ProcessInfo.processInfo.environment["SSH_PORT"], + let port = Int(_port) else { + throw XCTSkip("MISSING ENVIRONMENT VARIABLES - SSH_PORT") + } + guard + let username = ProcessInfo.processInfo.environment["SSH_USERNAME"] else { + throw XCTSkip("MISSING ENVIRONMENT VARIABLES - SSH_USERNAME") + } + guard + let password = ProcessInfo.processInfo.environment["SSH_PASSWORD"] else { + throw XCTSkip("MISSING ENVIRONMENT VARIABLES - SSH_PASSWORD") + } + + let client = try await SSHClient.connect( + host: host, + port: port, + authenticationMethod: .passwordBased(username: username, password: password), + hostKeyValidator: .acceptAnything(), + reconnect: .never + ) + + // example CLI command to run docker openSSH client locally: + // docker run -d -p 2222:2222 -e USER_NAME=citadel -e USER_PASSWORD=hunter2 -e PASSWORD_ACCESS=true lscr.io/linuxserver/openssh-server:latest + + // Q(heckj): What does it mean to "wantReply" with an environmentRequest? + let env: SSHChannelRequestEvent.EnvironmentRequest = .init(wantReply: false, name: "FOO", value: "bar") + let outputStreams = try await client.executeCommandStream("env", environment: [env], inShell: true) + + var accumulateStdOut: ByteBuffer = .init() + var accumulateStdErr: ByteBuffer = .init() + for try await event in outputStreams { + switch event { + case .stdout(let stdout): + // do something with stdout + accumulateStdOut.writeBytes(stdout.readableBytesView) + case .stderr(let stderr): + // do something with stderr + accumulateStdErr.writeBytes(stderr.readableBytesView) + } + } + + // exemplar output + // print("STDOUT: \(String(buffer: accumulateStdOut))") + + //STDOUT: SHELL=/bin/bash + //PWD=/config + //LOGNAME=citadel + //HOME=/config + //SSH_CONNECTION=192.168.215.1 59350 192.168.215.2 2222 + //USER=citadel + //SHLVL=1 + //SSH_CLIENT=192.168.215.1 59350 2222 + //PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + //MAIL=/var/mail/citadel + //_=/usr/bin/env + + let multilineString = String(buffer: accumulateStdOut) + XCTAssertTrue(multilineString.contains("USER=citadel")) + XCTAssertTrue(multilineString.contains("SHELL=/bin/bash")) + XCTAssertTrue(multilineString.contains("FOO=bar")) + + // print("STDERR: \(String(buffer: accumulateStdErr))") + XCTAssertTrue(String(buffer: accumulateStdErr).isEmpty) + + try await client.close() + } + }