Skip to content

Commit

Permalink
Merge pull request #82 from devon-mar/scp-tests
Browse files Browse the repository at this point in the history
Add SCP only tests
  • Loading branch information
devon-mar authored Dec 25, 2023
2 parents f82c424 + 05e97ee commit dbaf0b6
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 3 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,9 @@ jobs:
working-directory: tests

- name: Wait for containers to start
working-directory: tests
run: |
SSH_PORTS="2222 2223"
SSH_PORTS="2222 2223 2224"
for p in $SSH_PORTS; do
echo "::group::Wait for container $p to start"
for i in {1..20}; do ssh-keyscan -p $p localhost && break || echo -e "\033[0;33mNot started yet ($i)\033[0m" && sleep 1; done
Expand All @@ -99,6 +100,11 @@ jobs:
- name: Run tests
run: poetry run pytest -v tests

- name: Show Docker logs
if: ${{ always() }}
run: docker-compose logs
working-directory: tests

docs:
runs-on: ubuntu-latest
steps:
Expand Down
3 changes: 2 additions & 1 deletion nornir_paramiko/plugins/tasks/paramiko_sftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ def paramiko_sftp(
if compare is True
else None
)
assert sftp_client is not None
if compare is True:
assert sftp_client is not None
files_changed = actions[action](task, scp_client, sftp_client, src, dst, dry_run)
return Result(
host=task.host, changed=bool(files_changed), files_changed=files_changed
Expand Down
142 changes: 142 additions & 0 deletions tests/.null-ls_413347_test_paramiko_sftp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import random
import shutil
import string
import tempfile
from pathlib import Path

import pytest
from nornir.core import Nornir

from nornir_paramiko.plugins.tasks import paramiko_command, paramiko_sftp


def random_str(len: int) -> str:
return "".join(
random.choice(string.ascii_lowercase + string.digits) for _ in range(len)
)


@pytest.fixture
def temp_dir():
tmp = tempfile.mkdtemp()
yield Path(tmp)
shutil.rmtree(tmp)


def test_paramiko_sftp(host: str, nr: Nornir, temp_dir: Path) -> None:
nr_filtered = nr.filter(name=host)

test_content = random_str(20)

host_file = f"/tmp/test_{random_str(5)}"

test_put_file = temp_dir.joinpath("test_put")

with open(test_put_file, "wt") as f:
f.write(test_content)
result = nr_filtered.run(
task=paramiko_sftp, action="put", src=str(test_put_file), dst=host_file
)

assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is True
assert host_result.files_changed == [host_file]

# Test idempotence
result = nr_filtered.run(
task=paramiko_sftp, action="put", src=str(test_put_file), dst=host_file
)
assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is False
assert host_result.files_changed == []

# Now change the content then put
test_content += "a"
with open(test_put_file, "wt") as f:
f.write(test_content)
result = nr_filtered.run(
task=paramiko_sftp, action="put", src=str(test_put_file), dst=host_file
)

assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is True
assert host_result.files_changed == [host_file]

# Now retrieve the file back from the host
test_get_file = temp_dir.joinpath("test_get")

result = nr_filtered.run(
task=paramiko_sftp, action="get", src=host_file, dst=str(test_get_file)
)
assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is True
assert host_result.files_changed == [str(test_get_file)]

with open(test_get_file, "rt") as f:
have_content = f.read()
assert have_content == test_content


def test_paramiko_sftp_dry_run(host: str, nr_dry_run: Nornir, temp_dir: Path) -> None:
nr_filtered = nr_dry_run.filter(name=host)

test_content = random_str(20)

host_file = f"/tmp/test_{random_str(5)}"

test_put_file = temp_dir.joinpath("test_put")

with open(test_put_file, "wt") as f:
f.write(test_content)
result = nr_filtered.run(
task=paramiko_sftp, action="put", src=str(test_put_file), dst=host_file
)

assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is True
assert host_result.files_changed == [host_file]

# Check that the file was not written
result = nr_filtered.run(task=paramiko_command, command=f"test -f '{host_file}'")
assert result.failed is True # because the file wasn't written


def test_paramiko_scp_only_host(nr_dry_run: Nornir, temp_dir: Path) -> None:
host = "alpinescp"
nr_filtered = nr_dry_run.filter(name=host)

test_content = random_str(20)

host_file = f"/tmp/test_{random_str(5)}"

test_put_file = temp_dir.joinpath("test_put")

with open(test_put_file, "wt") as f:
f.write(test_content)
result = nr_filtered.run(
task=paramiko_sftp,
action="put",
src=str(test_put_file),
dst=host_file,
compare=False,
)

assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is True
assert host_result.files_changed == [host_file]

# Check that the file was not written
result = nr_filtered.run(task=paramiko_command, command=f"test -f '{host_file}'")
assert result.failed is False # because the file wasn't written
5 changes: 5 additions & 0 deletions tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM alpine:latest
RUN apk add --no-cache dropbear dropbear-scp
RUN mkdir /root/.ssh/ \
&& echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEq2cLqs++uwJh6xLTy4nX20UDfbgb6cDZl2nNkJEKud" > /root/.ssh/authorized_keys
ENTRYPOINT ["dropbear", "-EFR"]
2 changes: 2 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ def nr_dry_run():


def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
if "host" not in metafunc.fixturenames:
return
metafunc.parametrize("host", ("password", "key"))
7 changes: 7 additions & 0 deletions tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,10 @@ services:
PUBLIC_KEY: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEq2cLqs++uwJh6xLTy4nX20UDfbgb6cDZl2nNkJEKud
ports:
- 2223:2222
alpinescp:
image: alpinescp
build:
context: .
dockerfile: Dockerfile
ports:
- "2224:22"
8 changes: 8 additions & 0 deletions tests/inventory/hosts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ key:
paramiko:
extras:
key_filename: tests/id_ed25519
alpinescp:
hostname: 127.0.0.1
port: 2224
username: root
connection_options:
paramiko:
extras:
key_filename: tests/id_ed25519
81 changes: 80 additions & 1 deletion tests/test_paramiko_sftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import pytest
from nornir.core import Nornir

from nornir_paramiko.exceptions import CommandError
from nornir_paramiko.plugins.tasks import paramiko_command, paramiko_sftp


Expand Down Expand Up @@ -110,3 +109,83 @@ def test_paramiko_sftp_dry_run(host: str, nr_dry_run: Nornir, temp_dir: Path) ->
# Check that the file was not written
result = nr_filtered.run(task=paramiko_command, command=f"test -f '{host_file}'")
assert result.failed is True # because the file wasn't written


def test_paramiko_scp_only_host_dry_run(nr_dry_run: Nornir, temp_dir: Path) -> None:
host = "alpinescp"
nr_filtered = nr_dry_run.filter(name=host)

test_content = random_str(20)

host_file = f"/tmp/test_{random_str(5)}"

test_put_file = temp_dir.joinpath("test_put")

with open(test_put_file, "wt") as f:
f.write(test_content)
result = nr_filtered.run(
task=paramiko_sftp,
action="put",
src=str(test_put_file),
dst=host_file,
compare=False,
)

assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is True
assert host_result.files_changed == [str(test_put_file)]

# Check that the file was not written
result = nr_filtered.run(task=paramiko_command, command=f"test -f '{host_file}'")
assert result.failed is True # because the file wasn't written


def test_paramiko_scp_only_host(nr: Nornir, temp_dir: Path) -> None:
host = "alpinescp"
nr_filtered = nr.filter(name=host)

test_content = random_str(20)

host_file = f"/tmp/test_{random_str(5)}"

test_put_file = temp_dir.joinpath("test_put")

with open(test_put_file, "wt") as f:
f.write(test_content)
result = nr_filtered.run(
task=paramiko_sftp,
action="put",
src=str(test_put_file),
dst=host_file,
compare=False,
)

assert result.failed is False
assert len(result[host]) == 1
host_result = result[host][0]
assert host_result.changed is True
assert host_result.files_changed == [str(test_put_file)]

# Check that the file was written
result = nr_filtered.run(task=paramiko_command, command=f"test -f '{host_file}'")
assert result.failed is False


def test_paramiko_scp_only_host_compare(nr: Nornir, temp_dir: Path) -> None:
host = "alpinescp"
nr_filtered = nr.filter(name=host)

host_file = f"/tmp/test_{random_str(5)}"

test_put_file = temp_dir.joinpath("test_put")

result = nr_filtered.run(
task=paramiko_sftp,
action="put",
src=str(test_put_file),
dst=host_file,
compare=True,
)
assert result.failed is True # host does not support SFTp

0 comments on commit dbaf0b6

Please sign in to comment.