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

Add RemoteEnv tests using SshService testing infrastructure #557

Merged
merged 380 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
380 commits
Select commit Hold shift + click to select a range
447aa6f
ignore some doc build errors
bpkroth Apr 17, 2023
60c4787
minor windows tweaks
bpkroth Apr 17, 2023
f603a49
correction
bpkroth Apr 17, 2023
bed054e
fixups for windows
bpkroth Apr 17, 2023
bcfab8a
minor tweak
bpkroth Apr 17, 2023
20349f1
unnecessary
bpkroth Apr 17, 2023
61afd3a
remove an unnecessary import
bpkroth Apr 17, 2023
503698e
Merge branch 'main' into mypy-typing-mlos_bench
bpkroth Apr 17, 2023
c56bd42
cleanup merge
bpkroth Apr 17, 2023
9ab5246
Merge branch 'mypy-typing-mlos_bench' into add-ssh-support
bpkroth Apr 18, 2023
95aa63d
wip: bringing ssh support up to speed with mypy changes, refactoring …
bpkroth Apr 18, 2023
220f218
wip: split host and os ops vs provisioning more
bpkroth Apr 18, 2023
a988fdb
remove old file
bpkroth Apr 18, 2023
ca6e65a
finish refactor
bpkroth Apr 18, 2023
8946ba4
adding ssh services
bpkroth Apr 18, 2023
5e434a2
Merge branch 'main' into add-ssh-support (with conflicts)
bpkroth Apr 19, 2023
62e608c
merge conflict fixups
bpkroth Apr 19, 2023
57010b2
Merge branch 'main' into add-ssh-support
bpkroth Apr 21, 2023
a86b5a7
wip: new client library
bpkroth Apr 21, 2023
152ae74
tweaks
bpkroth Apr 21, 2023
3147142
stub file for fileshare services
bpkroth Apr 21, 2023
61f3351
wip
bpkroth Apr 22, 2023
23dfdbf
Merge branch 'main' into add-ssh-support
bpkroth Aug 24, 2023
ab968bd
merge cleanup
bpkroth Aug 24, 2023
b98d399
cleanup
bpkroth Aug 24, 2023
b4ae58c
fixups
bpkroth Aug 24, 2023
744cddf
rename
bpkroth Aug 24, 2023
1fd22e2
fixups
bpkroth Aug 24, 2023
1a21795
remove other PR work
bpkroth Aug 24, 2023
792c62d
fixup tests and provide schemas
bpkroth Aug 24, 2023
67a81d6
remove other PR work
bpkroth Aug 24, 2023
c6b9413
Merge branch 'main' into reorg-prep-for-ssh-support
bpkroth Aug 24, 2023
45ef444
switch some params around for better readability of unnamed boolean args
bpkroth Aug 25, 2023
eff7b0b
restore previous behavior
bpkroth Aug 25, 2023
b6ad16e
log correct details
bpkroth Aug 25, 2023
6c86928
fixup
bpkroth Aug 25, 2023
c6fa91b
restore old style
bpkroth Aug 25, 2023
423639d
fixups
bpkroth Aug 25, 2023
b1b88fa
fixup
bpkroth Aug 25, 2023
5ff8b20
Merge branch 'main' into reorg-prep-for-ssh-support
bpkroth Aug 25, 2023
ad406c7
restore the files we removed in the staging branch
bpkroth Aug 28, 2023
038ab9a
cleanup the container more quickly by default
bpkroth Aug 28, 2023
c3fece5
test env fixups
bpkroth Aug 28, 2023
b5cc0fd
wip: attempting to get networking to work for testing across platforms
bpkroth Aug 28, 2023
f7ea4bb
Workaround an upstream conda vs. base devcontainer image dependency m…
bpkroth Aug 28, 2023
fc1c50d
Merge branch 'fixup-devcontainer-rebuilds' into add-ssh-support
bpkroth Aug 28, 2023
4c5b6d2
tweaks to test config
bpkroth Aug 29, 2023
bba9906
switch to docker compose
bpkroth Aug 29, 2023
6ac48cb
wip: test harness code for ssh service
bpkroth Aug 30, 2023
032be72
more ssh test infrastructure
bpkroth Aug 30, 2023
510bbb9
improvements
bpkroth Aug 30, 2023
b03766a
fixups
bpkroth Aug 30, 2023
cb0a68d
fixups for windows
bpkroth Aug 30, 2023
330c154
wip
bpkroth Aug 30, 2023
71eca2d
add pid
bpkroth Aug 30, 2023
365196a
ssh config schema support
bpkroth Aug 31, 2023
29be25e
rename
bpkroth Aug 31, 2023
51698e1
add more schema properties and test cases
bpkroth Aug 31, 2023
8bdca2a
more ssh work
bpkroth Aug 31, 2023
64dba8d
add ssh dependencies
bpkroth Sep 1, 2023
888987a
wip
bpkroth Sep 1, 2023
87b1d09
wip
bpkroth Sep 1, 2023
21a5a7f
reorg for debugging aid
bpkroth Sep 5, 2023
009139d
wip
bpkroth Sep 5, 2023
7f0b07c
test example implementation that uses a single background thread to r…
bpkroth Sep 6, 2023
2a18624
wip
bpkroth Sep 7, 2023
c5adf7b
revert and add timing to convince myself that these things do in fact…
bpkroth Sep 7, 2023
709038c
wip
bpkroth Sep 8, 2023
7bd5570
Merge branch 'main' into add-ssh-support
bpkroth Sep 12, 2023
78e82fc
reorg and fixups
bpkroth Sep 13, 2023
329291c
wip
bpkroth Sep 13, 2023
1380463
wip merging hacking into place
bpkroth Sep 13, 2023
aeed341
fixups
bpkroth Sep 14, 2023
14ea81b
implement basic event loop thread
bpkroth Sep 14, 2023
6c94be4
todo comments
bpkroth Sep 14, 2023
4a09f4d
wip
bpkroth Sep 14, 2023
b357868
adjust schemas to not require config if empty
bpkroth Sep 14, 2023
9cb4259
wip: initial ssh host service
bpkroth Sep 14, 2023
c1883ac
Merge branch 'main' into add-ssh-support
bpkroth Sep 18, 2023
42c1c59
change the signatures so we can use it with ssh
bpkroth Sep 18, 2023
f39c315
initial implementation of scp service
bpkroth Sep 18, 2023
b581210
Fixups to commit message checks to only happen during PR pushes (#509)
bpkroth Sep 18, 2023
8331423
wip: tests
bpkroth Sep 19, 2023
75d9d28
Merge branch 'main' into add-ssh-support
bpkroth Sep 21, 2023
f617635
fixup for ssh infra test
bpkroth Sep 22, 2023
0135b61
switch to random ports
bpkroth Sep 22, 2023
e80d08a
fixups
bpkroth Sep 22, 2023
7ae530c
start adding multiple server support
bpkroth Sep 22, 2023
94536a1
test both servers
bpkroth Sep 22, 2023
1e35cc0
fixups and initial remote execution test
bpkroth Sep 22, 2023
422eb0c
add tests for multiple servers
bpkroth Sep 22, 2023
f1e8ad5
comments
bpkroth Sep 22, 2023
b690835
imporved tests
bpkroth Sep 22, 2023
2c3248e
types
bpkroth Sep 22, 2023
be6897b
pylint tweaks
bpkroth Sep 22, 2023
0417fc3
skip some base class config tests
bpkroth Sep 22, 2023
3a7be1a
fixups
bpkroth Sep 23, 2023
9ab3c11
add reboot testing, handle dynamic port changes, make sure that thing…
bpkroth Sep 27, 2023
b1c269b
checks for non-graceful disconnects too
bpkroth Sep 27, 2023
1dae1c8
mark more tests as part of the same parallel group
bpkroth Sep 27, 2023
3e840c3
wip: file upload/download
bpkroth Sep 27, 2023
acfc137
fixups
bpkroth Sep 27, 2023
d22814a
check for error handling of non-existing files
bpkroth Sep 27, 2023
f1976d6
pylint
bpkroth Sep 27, 2023
d310169
recursive file copy tests
bpkroth Sep 27, 2023
129ff21
missing config test cases
bpkroth Sep 28, 2023
fa95a52
Merge remote-tracking branch 'upstream/main' into add-ssh-support
bpkroth Sep 28, 2023
0b3bf61
test group fixups
bpkroth Sep 28, 2023
48d4976
clear the client cache before starting that test
bpkroth Sep 28, 2023
497553e
Merge remote-tracking branch 'upstream/main' into add-ssh-support
bpkroth Sep 28, 2023
7a26b47
Add a README explaining how the testing infrastructure works
bpkroth Sep 28, 2023
4f4ec5d
pylint, mypy fixes
bpkroth Sep 28, 2023
0beecca
work around python 3.8 issues
bpkroth Sep 28, 2023
435bde4
remove hacking script
bpkroth Sep 28, 2023
bf1e77d
comments
bpkroth Sep 28, 2023
8fa4615
comments
bpkroth Sep 28, 2023
166c5ec
comments
bpkroth Sep 28, 2023
8fe4e02
Merge branch 'main' into add-ssh-support
bpkroth Sep 28, 2023
7c8ce8b
Merge branch 'main' into add-ssh-support
bpkroth Sep 29, 2023
87a3fcb
pylint
bpkroth Sep 29, 2023
bc89a63
refactor for windows support
bpkroth Sep 29, 2023
0f98006
prebuild the necessary docker services for windows
bpkroth Sep 29, 2023
cd990cc
prebuild the necessary docker services for windows
bpkroth Sep 29, 2023
42fab2c
split steps
bpkroth Sep 29, 2023
8f14360
move it sooner for debugging
bpkroth Sep 29, 2023
362ceca
Merge branch 'additional-remote-env-tests' into add-ssh-support
bpkroth Sep 29, 2023
d62a560
default to linux for containers
bpkroth Sep 29, 2023
4ebf335
workaround issues with windows ci by specifying the build platform
bpkroth Sep 29, 2023
e31a393
Add checks for Linux platform support from docker on host - Windows G…
bpkroth Sep 29, 2023
7662440
more
bpkroth Sep 29, 2023
51b67ff
restore
bpkroth Sep 29, 2023
b745f80
debugging
bpkroth Sep 29, 2023
540a386
remove platform spec
bpkroth Sep 29, 2023
2146d11
improvements for github windows action runner
bpkroth Sep 29, 2023
c22c518
builder or buildx support dne in windows
bpkroth Sep 29, 2023
370043c
allow nested run in container with cli args for testing
bpkroth Sep 29, 2023
ba07483
testing
bpkroth Sep 29, 2023
90d4558
add the host.docker.internal mapping to the devcontainer so we can re…
bpkroth Oct 2, 2023
8971541
tweaks for windows ci environment
bpkroth Oct 2, 2023
f973b09
unnecessary to split that out
bpkroth Oct 2, 2023
5ea9997
spelling
bpkroth Oct 2, 2023
09d3eec
Merge branch 'main' into add-ssh-support
motus Oct 5, 2023
3a3174e
Merge branch 'main' into add-ssh-support
bpkroth Oct 10, 2023
7b8f6a8
Merge branch 'main' into add-ssh-support
bpkroth Oct 11, 2023
109a324
Merge branch 'main' into add-ssh-support
motus Oct 17, 2023
430e2cb
disk space debugging
bpkroth Oct 18, 2023
bbcdde2
also list the docker images
bpkroth Oct 18, 2023
2a0f07a
fix a bug with mock responses not providing a method only called duri…
bpkroth Oct 18, 2023
5715a0c
allow optionally running in debug log level during nightly runs
bpkroth Oct 18, 2023
c0fe88e
Merge branch 'fix-magicmock-json-serialization-errors' into add-ssh-s…
bpkroth Oct 18, 2023
dfade61
more garbage collection
bpkroth Oct 18, 2023
7a6e562
more thorough gc
bpkroth Oct 18, 2023
98014e0
Merge branch 'main' into add-ssh-support
bpkroth Oct 18, 2023
aac2b9f
remove TODO comment
bpkroth Oct 19, 2023
9be45b2
ignore a known warning
bpkroth Oct 19, 2023
8bb4e96
Merge branch 'main' into add-ssh-support
motus Oct 19, 2023
9aba8a7
fixups
bpkroth Oct 19, 2023
3661bda
space debugging
bpkroth Oct 20, 2023
16ee957
timeout change
bpkroth Oct 20, 2023
05cabfe
addressing comments
bpkroth Oct 23, 2023
ee37493
revert NoneType change
bpkroth Oct 23, 2023
c54ea8a
implement force restart
bpkroth Oct 23, 2023
1b86d64
apply suggestions to support multiline commands
bpkroth Oct 23, 2023
f93b240
Merge branch 'main' into add-ssh-support
motus Oct 24, 2023
f406ac3
apply suggestions
bpkroth Oct 24, 2023
d07afc7
fixups post main merge
bpkroth Oct 24, 2023
acef755
fixup
bpkroth Oct 24, 2023
2d5cad2
backout some ci changes
bpkroth Oct 24, 2023
1c4a8ce
Merge branch 'main' into add-ssh-support
bpkroth Oct 24, 2023
06f7d76
remove comment
bpkroth Oct 24, 2023
b671732
Merge branch 'main' into add-ssh-support
bpkroth Oct 24, 2023
493e246
fixup method registering
bpkroth Oct 25, 2023
3d8f3a9
wip: convert to context manager
bpkroth Oct 25, 2023
0818633
fixups to tests to make mock_operations methods
bpkroth Oct 25, 2023
0cb41c1
enter contexts to use ssh services
bpkroth Oct 25, 2023
1dceae2
fixup method registering
bpkroth Oct 25, 2023
ed4eb40
wip: add context manager support to Services
bpkroth Oct 25, 2023
fa8cab9
fixups to tests to make mock_operations methods
bpkroth Oct 25, 2023
45a7ce8
add a basic sanity check
bpkroth Oct 25, 2023
ec250ce
more
bpkroth Oct 25, 2023
a8cc9eb
Merge branch 'main' into context-manager-support-for-services
bpkroth Oct 25, 2023
f2cdce8
remove Self annotation that I was playing with
bpkroth Oct 25, 2023
ff9f664
remove requirement that service methods be methods and not functions
bpkroth Oct 25, 2023
d73f29b
Revert "fixups to tests to make mock_operations methods"
bpkroth Oct 25, 2023
a60afae
make service context reentrant
bpkroth Oct 25, 2023
548b7b1
Merge branch 'context-manager-support-for-services' into add-ssh-supp…
bpkroth Oct 25, 2023
a4f8544
Merge branch 'add-ssh-support-with-context-manager' into add-ssh-support
bpkroth Oct 25, 2023
49bd826
fixu
bpkroth Oct 25, 2023
6727ebf
removed
bpkroth Oct 25, 2023
4d7b603
Merge branch 'main' into add-ssh-support
bpkroth Oct 25, 2023
4644b0a
Revert "fixups to tests to make mock_operations methods"
bpkroth Oct 25, 2023
1dbe71d
make service context reentrant
bpkroth Oct 25, 2023
6ccecad
Update mlos_bench/mlos_bench/services/remote/ssh/ssh_host_service.py
bpkroth Oct 26, 2023
73e70e2
Update mlos_bench/mlos_bench/services/remote/ssh/ssh_service.py
bpkroth Oct 26, 2023
6d2132a
Update mlos_bench/mlos_bench/services/remote/ssh/ssh_service.py
bpkroth Oct 26, 2023
57f2266
revamp to separate out async event loop context helper
bpkroth Oct 26, 2023
eb76bfe
Extract event loop context manager from SSH PR
bpkroth Oct 26, 2023
6584b45
add a test for running coroutines in the background
bpkroth Oct 26, 2023
1a7d232
Merge branch 'add-asyncio-event-loop-context-manager' into add-ssh-su…
bpkroth Oct 26, 2023
02edc57
comments
bpkroth Oct 26, 2023
7c6008d
comment cleanup
bpkroth Oct 26, 2023
513e372
comment
bpkroth Oct 26, 2023
e2b06dd
Merge branch 'main' into add-ssh-support
bpkroth Oct 26, 2023
9a134e5
refactor
bpkroth Oct 26, 2023
1864497
split out remote ssh fixtures for reuse elsewhere
bpkroth Oct 26, 2023
68b7697
add basic ssh service configs
bpkroth Oct 26, 2023
4cae155
initial remote ssh env tests
bpkroth Oct 26, 2023
6392ffa
Merge branch 'main' into additional-remote-env-tests
bpkroth Oct 26, 2023
66fe71f
fixups
bpkroth Oct 26, 2023
5929f8f
merge conflict
bpkroth Oct 26, 2023
afab0aa
comments
bpkroth Oct 26, 2023
d7bdc78
fixups
bpkroth Oct 26, 2023
45c7d32
don't require hostops if we aren't waiting on boot (hack for now - ne…
bpkroth Oct 26, 2023
4866f1f
comments
bpkroth Oct 26, 2023
c529a1c
include local exec service (only comes by default from launcher)
bpkroth Oct 26, 2023
d0bd040
mark required_args for local download service too
bpkroth Oct 26, 2023
efff26d
comments
bpkroth Oct 26, 2023
6dc18cd
tweak
bpkroth Oct 26, 2023
dd61d82
fixups
bpkroth Oct 26, 2023
4f48046
docs
bpkroth Oct 26, 2023
8e262d8
make sure to re-assign services whenever we register new methods
bpkroth Oct 26, 2023
81ee5cc
debugging
bpkroth Oct 26, 2023
c8d28cc
tweaks to debug vs. batch run testing in vscode
bpkroth Oct 27, 2023
1c4ea49
fixup bad merge
bpkroth Oct 27, 2023
08fc04d
allow debugging by waiting longer before timingout the container
bpkroth Oct 27, 2023
3b31425
convert SFTP exceptions to FileNotFound for RemoteEnv
bpkroth Oct 27, 2023
9e145be
debugging aids
bpkroth Oct 27, 2023
c89ce0b
Merge branch 'main' into additional-remote-env-tests
bpkroth Oct 27, 2023
2405750
Merge branch 'main' into additional-remote-env-tests
bpkroth Oct 27, 2023
218d36a
test fixups
bpkroth Oct 27, 2023
ce58473
fix bad merge
bpkroth Oct 27, 2023
dd8f15a
Merge branch 'main' into additional-remote-env-tests
motus Oct 27, 2023
561e4c5
comments
bpkroth Oct 27, 2023
9ef3ffa
requires docker
bpkroth Oct 27, 2023
270ae4b
requires docker
bpkroth Oct 27, 2023
03e5a02
add tests for teardown too
bpkroth Oct 27, 2023
8272a32
enforce the higher code coverage requirements
bpkroth Oct 27, 2023
7d80331
Merge branch 'main' into additional-remote-env-tests
bpkroth Oct 27, 2023
5385ac8
Merge branch 'main' into additional-remote-env-tests
bpkroth Oct 27, 2023
637181a
cleanup merge conflict
bpkroth Oct 27, 2023
2972aaf
cleanup after ourselves
bpkroth Oct 27, 2023
7100458
comments
bpkroth Oct 27, 2023
55575eb
Merge branch 'main' into additional-remote-env-tests
bpkroth Oct 27, 2023
3e3d268
Merge branch 'main' into additional-remote-env-tests
motus Oct 27, 2023
7809d81
Update mlos_bench/mlos_bench/services/remote/ssh/ssh_host_service.py
bpkroth Nov 1, 2023
8ba102d
Update mlos_bench/mlos_bench/environments/local/local_fileshare_env.py
bpkroth Nov 1, 2023
673121a
Merge branch 'main' into additional-remote-env-tests
bpkroth Nov 1, 2023
df49478
Merge branch 'main' into additional-remote-env-tests
bpkroth Nov 1, 2023
21d6472
fixups
bpkroth Nov 1, 2023
ba899a9
Merge branch 'main' into additional-remote-env-tests
bpkroth Nov 1, 2023
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
6 changes: 5 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
"justMyCode": false,
"env": {
// When debugging tests, only run a single pytest worker instance.
"PYTEST_ADDOPTS": "-n1 --no-cov --dist=no --log-level=DEBUG"
"PYTEST_ADDOPTS": "-n1 --no-cov --dist=no --log-level=DEBUG",
// For debugging the ssh containers in particular, let them
// live a little longer before automatically stopping them.
// See Also: mlos_bench/tests/services/remote/ssh/
"TIMEOUT": "1800"
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ PYTEST_OPTIONS :=
SKIP_COVERAGE := $(shell echo $${SKIP_COVERAGE:-} | grep -i -x -e 1 -e true)

ifeq ($(SKIP_COVERAGE),)
PYTEST_OPTIONS += --cov=. --cov-append --cov-fail-under=0.91 --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml --local-badge-output-dir=doc/source/badges/
PYTEST_OPTIONS += --cov=. --cov-append --cov-fail-under=0.92 --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml --local-badge-output-dir=doc/source/badges/
endif

# Run the pytest target on only the modules that have changed recently, but
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"class": "mlos_bench.services.local.local_exec.LocalExecService"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"class": "mlos_bench.services.remote.ssh.ssh_fileshare.SshFileShareService",
"config": {
// don't check host keys
"ssh_known_hosts_path": null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"class": "mlos_bench.services.remote.ssh.ssh_host_service.SshHostService",
"config": {
// don't check host keys
"ssh_known_hosts_path": null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def setup(self, tunables: TunableGroups, global_config: Optional[dict] = None) -
params = self._get_env_params()
params["PWD"] = self._temp_dir
for (path_from, path_to) in self._expand(self._upload, params):
self._file_share_service.upload(self.config, self._config_loader_service.resolve_path(
self._file_share_service.upload(self._params, self._config_loader_service.resolve_path(
path_from, extra_paths=[self._temp_dir]), path_to)
return self._is_ready

Expand All @@ -140,13 +140,16 @@ def _download_files(self, ignore_missing: bool = False) -> None:
params["PWD"] = self._temp_dir
for (path_from, path_to) in self._expand(self._download, params):
try:
self._file_share_service.download(self.config,
self._file_share_service.download(self._params,
path_from, self._config_loader_service.resolve_path(
path_to, extra_paths=[self._temp_dir]))
except FileNotFoundError as ex:
_LOG.warning("Cannot download: %s", path_from)
if not ignore_missing:
raise ex
except Exception as ex:
_LOG.exception("Cannot download %s to %s", path_from, path_to)
raise ex

def run(self) -> Tuple[Status, Optional[Dict[str, TunableValue]]]:
"""
Expand Down
7 changes: 4 additions & 3 deletions mlos_bench/mlos_bench/environments/remote/remote_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ def __init__(self,
"RemoteEnv requires a service that supports remote execution operations"
self._remote_exec_service: SupportsRemoteExec = self._service

assert self._service is not None and isinstance(self._service, SupportsHostOps), \
"RemoteEnv requires a service that supports host operations"
self._host_service: SupportsHostOps = self._service
if self._wait_boot:
assert self._service is not None and isinstance(self._service, SupportsHostOps), \
"RemoteEnv requires a service that supports host operations"
self._host_service: SupportsHostOps = self._service

def setup(self, tunables: TunableGroups, global_config: Optional[dict] = None) -> bool:
"""
Expand Down
1 change: 1 addition & 0 deletions mlos_bench/mlos_bench/environments/script_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def _get_env_params(self) -> Dict[str, str]:
# Only rename specified - use it.
rename = self._shell_env_params_rename.copy()
else:
# FIXME: We should not be exposing all params by default.
# Neither `shell_env_params` nor rename are specified - use all params.
rename = {self._RE_INVALID.sub("_", key): key for key in self._params}
else:
Expand Down
10 changes: 9 additions & 1 deletion mlos_bench/mlos_bench/services/remote/ssh/ssh_fileshare.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import logging

from asyncssh import scp, SFTPError, SSHClientConnection
from asyncssh import scp, SFTPError, SFTPNoSuchFile, SFTPFailure, SSHClientConnection

from mlos_bench.services.base_fileshare import FileShareService
from mlos_bench.services.remote.ssh.ssh_service import SshService
Expand Down Expand Up @@ -58,6 +58,8 @@ async def _start_file_copy(self, params: dict, mode: CopyMode,
If the local OS returns an error.
SFTPError
If the remote OS returns an error.
FileNotFoundError
If the remote file does not exist, the SFTPError is converted to a FileNotFoundError.
"""
connection, _ = await self._get_client_connection(params)
srcpaths: Union[str, Tuple[SSHClientConnection, str]]
Expand Down Expand Up @@ -87,6 +89,12 @@ def download(self, params: dict, remote_path: str, local_path: str, recursive: b
file_copy_future.result()
except (OSError, SFTPError) as ex:
_LOG.error("Failed to download %s to %s from %s: %s", remote_path, local_path, params, ex)
if isinstance(ex, SFTPNoSuchFile) or (
isinstance(ex, SFTPFailure) and ex.code == 4
and any(msg.lower() in ex.reason.lower() for msg in ("File not found", "No such file or directory"))
):
_LOG.warning("File %s does not exist on %s", remote_path, params)
raise FileNotFoundError(f"File {remote_path} does not exist on {params}") from ex
raise ex

def upload(self, params: dict, local_path: str, remote_path: str, recursive: bool = True) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ async def _run_cmd(self, params: dict, script: Iterable[str], env_params: dict)
env_script_lines = [f"export {name}='{value}'" for (name, value) in env_params.items()]
script_lines = env_script_lines + [line_split for line in script for line_split in line.splitlines()]
# Note: connection.run() uses "exec" with a shell by default.
return await connection.run('\n'.join(script_lines),
script_str = '\n'.join(script_lines)
_LOG.debug("Running script on %s:\n%s", connection, script_str)
return await connection.run(script_str,
check=False,
timeout=self._request_timeout,
env=env_params)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Test config for test_ssh_env.py
{
"class": "mlos_bench.environments.composite_env.CompositeEnv",
"description": "Test Environment for RemoteEnv via local SSH test infrastructure",
"name": "composite_remote_ssh_env",

"include_services": [
// from the built in configs
"services/local/local_exec_service.jsonc",
"services/remote/ssh/ssh_host_service.jsonc",
"services/remote/ssh/ssh_fileshare_service.jsonc"
],

"config": {
"children": [
{
"class": "mlos_bench.environments.remote.remote_env.RemoteEnv",
"name": "remote_ssh_env",
"config": {
"required_args": [
"ssh_hostname",
"ssh_port",
"ssh_username",
"ssh_priv_key_path"
],
"shell_env_params": [
"ssh_username"
],
"setup": [
"echo 'Preparing output.csv' >&2",
"echo 'metric,value' | tee output.csv"
],
"run": [
// write a basic results csv file we can download and compare with
"echo 'Generating test metrics output ...' >&2",
// Check that we connected to the test server.
"echo \"hostname,`hostname`\" | tee -a output.csv",
// Test environment variables
"echo \"username,${ssh_username}\" | tee -a output.csv",
"echo score,0.9 | tee -a output.csv",
"echo 'Done' >&2",
// Wait a moment (mostly for debugging)
"echo 'Sleeping ...' >&2",
//"sleep 10",
"echo 'Done' >&2"
],
"teardown": [
"rm output.csv",
"echo 'teardown,complete' | tee teardown.txt"
]
}
},
{
"class": "mlos_bench.environments.local.local_fileshare_env.LocalFileShareEnv",
"name": "local_ssh_env",
"config": {
// these are needed by the SshFileShareService
// FIXME: Can we only include these in the CompositeEnv and have them propagate down?
"required_args": [
"ssh_hostname",
"ssh_port",
"ssh_username",
"ssh_priv_key_path"
],
// Download happens *prior* to teardown, so this should succeed.
"download": [
{
"from": "output.csv",
// Download to the temporary directory, not the current working directory.
"to": "$PWD/output-downloaded.csv"
}
],
"read_results_file": "output-downloaded.csv",
"teardown": [
"test ! -e output-downloaded.csv"
]
}
}
]
}
}
38 changes: 38 additions & 0 deletions mlos_bench/mlos_bench/tests/environments/remote/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
"""
Helpers for RemoteEnv tests.
"""

from typing import Any, Dict, List, Tuple

from mlos_bench.environments.remote.remote_env import RemoteEnv
from mlos_bench.services.config_persistence import ConfigPersistenceService
from mlos_bench.services.remote.ssh.ssh_host_service import SshHostService
from mlos_bench.services.remote.ssh.ssh_fileshare import SshFileShareService
from mlos_bench.tunables.tunable_groups import TunableGroups


def create_remote_ssh_env(tunable_groups: TunableGroups, config: Dict[str, Any]) -> RemoteEnv:
"""
Create a RemoteEnv with the given configuration that uses SshServices.

Parameters
----------
tunable_groups : TunableGroups
Tunable parameters (usually come from a fixture).
config : Dict[str, Any]
Environment configuration.

Returns
-------
env : RemoteEnv
A new instance of the local environment.
"""
service = ConfigPersistenceService()
service.register(SshHostService().export())
service.register(SshFileShareService().export())

return RemoteEnv(name="TestRemoveEnv", config=config, tunables=tunable_groups, service=service)
16 changes: 16 additions & 0 deletions mlos_bench/mlos_bench/tests/environments/remote/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
"""
Fixtures for the RemoteEnv tests using SSH Services.
"""

import mlos_bench.tests.services.remote.ssh.fixtures as ssh_fixtures

# Expose those as local names.
ssh_test_server_hostname = ssh_fixtures.ssh_test_server_hostname
ssh_test_server = ssh_fixtures.ssh_test_server
alt_test_server = ssh_fixtures.alt_test_server
ssh_host_service = ssh_fixtures.ssh_host_service
ssh_fileshare_service = ssh_fixtures.ssh_fileshare_service
61 changes: 61 additions & 0 deletions mlos_bench/mlos_bench/tests/environments/remote/test_ssh_env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
"""
Unit tests for RemoveEnv benchmark environment via local SSH test services.
"""

from typing import Dict

import os
import sys

import pytest

from mlos_bench.services.config_persistence import ConfigPersistenceService
from mlos_bench.tunables.tunable import TunableValue
from mlos_bench.tunables.tunable_groups import TunableGroups

from mlos_bench.tests import requires_docker
from mlos_bench.tests.environments import check_env_success
from mlos_bench.tests.services.remote.ssh import SshTestServerInfo

if sys.version_info < (3, 10):
from importlib_resources import files
else:
from importlib.resources import files


@requires_docker
@pytest.mark.xdist_group("ssh_test_server")
def test_remote_ssh_env(tunable_groups: TunableGroups, ssh_test_server: SshTestServerInfo) -> None:
"""
Produce benchmark and telemetry data in a local script and read it.
"""
global_config: Dict[str, TunableValue] = {
"ssh_hostname": ssh_test_server.hostname,
"ssh_port": ssh_test_server.get_port(),
"ssh_username": ssh_test_server.username,
"ssh_priv_key_path": ssh_test_server.id_rsa_path,
}

service = ConfigPersistenceService(config={"config_path": [str(files("mlos_bench.tests.config"))]})
config_path = service.resolve_path("environments/remote/test_ssh_env.jsonc")
env = service.load_environment(config_path, tunable_groups, global_config=global_config, service=service)

check_env_success(
env, tunable_groups,
expected_results={
"hostname": ssh_test_server.service_name,
"username": ssh_test_server.username,
"score": 0.9,
},
expected_telemetry=[],
)
assert not os.path.exists(os.path.join(os.getcwd(), "output-downloaded.csv")), \
"output-downloaded.csv should have been cleaned up by temp_dir context"


if __name__ == "__main__":
pytest.main(["-n1", __file__])
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

import pytest

from asyncssh import SFTPError

from mlos_bench.services.remote.ssh.ssh_host_service import SshHostService
from mlos_bench.services.remote.ssh.ssh_fileshare import SshFileShareService
from mlos_bench.util import path_join
Expand Down Expand Up @@ -167,7 +165,7 @@ def test_ssh_fileshare_download_file_dne(ssh_test_server: SshTestServerInfo,
temp_file.flush()
temp_file.close()

with pytest.raises(SFTPError):
with pytest.raises(FileNotFoundError):
ssh_fileshare_service.download(
params=config,
remote_path="/tmp/file-dne.txt",
Expand Down