Skip to content

Commit e32441a

Browse files
[Testing] Test SSH file transfer with images. (#208)
* lots of changes, sort out. * still working, needs a bit more tidying up. * Continue working. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Tidy ups. * Fix linting. * Tidy ups and documentation. * Add documentation. * Try different Dockerfile for linux. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix issue after rebase. * Remove breakpoint. * Don't use singularity, docker or nothing. * Rework ssh setup. * Fix connection refused issue. * Use run not POpen for actions. * try in detachted state. * Add error messages on docker setup. * run linting. * update connection failed error message. * Test version working locally on linux but only can connect with sudo. * Try freeing up and using the free port. * Test sudo service only on linux. * Add sudo to docker setup commands. * test with auto add policy. * Really restrict to the connect call. * restrict to tests of interest temporarily. * Fix to port 3306 in tests and for paramiko. * Extend port to rclone. * Use environment variable to set port. * Add all OS back. * try remove tag for windows. * Update docker commands for windows. * Fix nonsense docker build command. * Only run when docker running and on ubuntu on runners. * Try build and run docker only once per session. * Teardown image at end of ssh tests, factor out ssh tests. * SPlit ssh tests. * Add sudo to the docker teardown commands for Linux. * try class scope of setup ssh container. * Try move ssh fixture to classes. * Try a different command to shutdown on linux. * Tidy ups and some docs. * Extend to macOS. * Finish tidying up docstrings. * Change ssh test image name and fix docstring. * Small tidy ups. * Small fixes after rebase. * More fix.es * Fix CI. * Skip tests on macOS. * Refactor transfer tests. * Continue refactoring. * Fix tests again. * Update CI script. * Update CI. * Fix imports after rebase. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Delete config to fix tests. * Remove test module that was accidentally readded by git. * Delete now unused file. * Do not append por with : if it is default (22). * Move test setup_rclone_config_for_ssh into setup_ssh_connection. * Extend SSH tests not run message. * Improve test skipped message. * Fix duplicate if / else statement. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 094696d commit e32441a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+800
-491
lines changed

.github/workflows/code_test_and_deploy.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
# macos-14 is M1, macos-13 is intel. Run on earliest and
3333
# latest python versions. All python versions are tested in
3434
# the weekly cron job.
35-
os: [windows-latest, ubuntu-latest, macos-14, macos-13]
35+
os: [ ubuntu-latest, windows-latest, macos-14, macos-13]
3636
# Test all Python versions for cron job, and only first/last for other triggers
3737
python-version: ${{ fromJson(github.event_name == 'schedule' && '["3.9", "3.10", "3.11", "3.12"]' || '["3.9", "3.12"]') }}
3838

@@ -57,8 +57,17 @@ jobs:
5757
run: |
5858
python -m pip install --upgrade pip
5959
pip install .[dev]
60-
- name: Test
61-
run: pytest
60+
# run SSH tests only on Linux because Windows and macOS
61+
# are already run within a virtual container and so cannot
62+
# run Linux containers because nested containerisation is disabled.
63+
- name: Test SSH (Linux only)
64+
if: runner.os == 'Linux'
65+
run: |
66+
sudo service mysql stop # free up port 3306 for ssh tests
67+
pytest tests/tests_transfers/ssh
68+
- name: All Other Tests
69+
run: |
70+
pytest --ignore tests/tests_transfers/ssh
6271
6372
build_sdist_wheels:
6473
name: Build source distribution

datashuttle/configs/canonical_configs.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from __future__ import annotations
1111

12+
import os
1213
from typing import (
1314
TYPE_CHECKING,
1415
Dict,
@@ -52,6 +53,14 @@ def keys_str_on_file_but_path_in_class() -> list[str]:
5253
]
5354

5455

56+
def get_default_ssh_port() -> int:
57+
"""Get the default port used for SSH connections."""
58+
if "DS_SSH_PORT" in os.environ:
59+
return int(os.environ["DS_SSH_PORT"])
60+
else:
61+
return 22
62+
63+
5564
# -----------------------------------------------------------------------------
5665
# Check Configs
5766
# -----------------------------------------------------------------------------

datashuttle/utils/data_transfer.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ def build_a_list_of_all_files_and_folders_to_transfer(self) -> List[str]:
164164
self.update_list_with_non_ses_sub_level_folders(
165165
extra_folder_names, extra_filenames, sub
166166
)
167-
168167
continue
169168

170169
# Datatype (sub and ses level) --------------------------------

datashuttle/utils/rclone.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from subprocess import CompletedProcess
77
from typing import Dict, List, Literal
88

9+
from datashuttle.configs import canonical_configs
910
from datashuttle.configs.config_class import Configs
1011
from datashuttle.utils import utils
1112
from datashuttle.utils.custom_types import TopLevelFolder
@@ -161,7 +162,7 @@ def setup_rclone_config_for_ssh(
161162
f"sftp "
162163
f"host {cfg['central_host_id']} "
163164
f"user {cfg['central_host_username']} "
164-
f"port 22 "
165+
f"port {canonical_configs.get_default_ssh_port()} "
165166
f"key_file {ssh_key_path.as_posix()}",
166167
pipe_std=True,
167168
)

datashuttle/utils/ssh.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import paramiko
1616

17+
from datashuttle.configs import canonical_configs
1718
from datashuttle.utils import utils
1819

1920
# -----------------------------------------------------------------------------
@@ -58,6 +59,7 @@ def connect_client_core(
5859
else None
5960
),
6061
look_for_keys=True,
62+
port=canonical_configs.get_default_ssh_port(),
6163
)
6264

6365

@@ -122,7 +124,9 @@ def get_remote_server_key(central_host_id: str):
122124
123125
"""
124126
transport: paramiko.Transport
125-
with paramiko.Transport(central_host_id) as transport:
127+
with paramiko.Transport(
128+
(central_host_id, canonical_configs.get_default_ssh_port())
129+
) as transport:
126130
transport.connect()
127131
key = transport.get_remote_server_key()
128132
return key
@@ -148,7 +152,15 @@ def save_hostkey_locally(key, central_host_id, hostkeys_path) -> None:
148152
149153
"""
150154
client = paramiko.SSHClient()
151-
client.get_host_keys().add(central_host_id, key.get_name(), key)
155+
156+
port = canonical_configs.get_default_ssh_port()
157+
host_key = f"[{central_host_id}]:{port}" if port != 22 else central_host_id
158+
159+
client.get_host_keys().add(
160+
host_key,
161+
key.get_name(),
162+
key,
163+
)
152164
client.get_host_keys().save(hostkeys_path.as_posix())
153165

154166

@@ -242,15 +254,16 @@ def connect_client_with_logging(
242254
f"Connection to {cfg['central_host_id']} made successfully."
243255
)
244256

245-
except Exception:
257+
except Exception as e:
246258
utils.log_and_raise_error(
247259
f"Could not connect to server. Ensure that \n"
248260
f"1) You have run setup_ssh_connection() \n"
249261
f"2) You are on VPN network if required. \n"
250262
f"3) The central_host_id: {cfg['central_host_id']} is"
251263
f" correct.\n"
252264
f"4) The central username:"
253-
f" {cfg['central_host_username']}, and password are correct.",
265+
f" {cfg['central_host_username']}, and password are correct."
266+
f"Original error: {e}",
254267
ConnectionError,
255268
)
256269

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ select = [
126126
"D", # pydocstyle
127127
]
128128
per-file-ignores = { "tests/*" = [
129-
"D" # ignore docstring formatting in tests for now
129+
"D", # ignore docstring formatting in tests for now
130+
"TID252"
130131
], "examples/*" = [
131132
"D400", # first line should end with a period.
132133
"D415", # first line should end with a period, question mark...

tests/__init__.py

Whitespace-only changes.

tests/tests_integration/base.py renamed to tests/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import warnings
22

33
import pytest
4-
import test_utils
4+
5+
from . import test_utils
56

67
TEST_PROJECT_NAME = "test_project"
78

tests/conftest.py

Lines changed: 0 additions & 46 deletions
This file was deleted.

tests/ssh_test_utils.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

0 commit comments

Comments
 (0)