Skip to content

Commit

Permalink
Covered "ssh-command" with tests and fixed all spotted bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
blackandred committed Oct 25, 2019
1 parent 7c9994d commit 5f59478
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ clean: ## Clean up the local build directory
${SUDO} rm -rf ./build ./infracheck.egg-info

unit_test: ## Run unit tests
${PY_BIN} -m unittest discover -s ./tests
${PY_BIN} -m unittest discover -s tests

coverage: ## Generate code coverage
coverage run --rcfile=.coveragerc --source . -m unittest discover -s ./tests
File renamed without changes.
8 changes: 6 additions & 2 deletions infracheck/checks/ssh-command
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class SshCommand:
out = e.output.decode('utf-8')
exit_code = e.returncode

truncated_output = (str(out)[-64:]).strip()
truncated_output = (str(out)[-256:]).strip()

if int(exit_code) != self.expected_exit_code:
return False, "Unexpected exit code %i with output: %s" % (exit_code, truncated_output)
Expand All @@ -106,6 +106,10 @@ class SshCommand:


if __name__ == '__main__':
if not getenv('HOST'):
print("HOST is mandatory")
exit(1)

app = SshCommand(
user=getenv('USER', 'root'),
host=getenv('HOST'),
Expand All @@ -125,4 +129,4 @@ if __name__ == '__main__':
status, message = app.main()

print(message)
exit(status)
exit(0 if status else 1)
File renamed without changes.
2 changes: 1 addition & 1 deletion tests/test_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
sys.path.append(path)

try:
from ..infracheck.infracheck.controller import Controller
from .infracheck.infracheck.controller import Controller
except ImportError as e:
from infracheck.infracheck.controller import Controller

Expand Down
2 changes: 1 addition & 1 deletion tests/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
sys.path.append(path)

try:
from ..infracheck.infracheck.repository import Repository
from .infracheck.infracheck.repository import Repository
except ImportError as e:
from infracheck.infracheck.repository import Repository

Expand Down
2 changes: 1 addition & 1 deletion tests/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
sys.path.append(path)

try:
from ..infracheck.infracheck.runner import Runner
from .infracheck.infracheck.runner import Runner
except ImportError as e:
from infracheck.infracheck.runner import Runner

Expand Down
56 changes: 56 additions & 0 deletions tests/test_ssh_command_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import unittest
import docker

from .utils import run_check
from .utils.ssh_test import TestThatRequiresSshServer


class SshCommandCheckTest(TestThatRequiresSshServer, unittest.TestCase):
docker_client: docker.DockerClient

def test_not_passed_host_raises_human_readable_message(self):
stdout: str
result: int

stdout, result, hooks_output = run_check('ssh-command', {}, {})

self.assertIn('HOST is mandatory', stdout)
self.assertFalse(result)

def test_success_case(self):
"""
Simple success case with expected keywords usage
:return:
"""

stdout: str
result: int

stdout, result, hooks_output = run_check('ssh-command', {
'HOST': 'localhost',
'PORT': 3222,
'USER': 'root',
'PASSWORD': 'root',
'SSH_OPTS': '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null',
'COMMAND': 'uname -a',
'EXPECTED_KEYWORDS': 'Linux',
'UNEXPECTED_KEYWORDS': 'Darwin'
}, {})

self.assertEqual('OK', stdout.strip())
self.assertTrue(result)

def test_invalid_password(self):
stdout: str
result: int

stdout, result, hooks_output = run_check('ssh-command', {
'HOST': 'localhost',
'PORT': 3222,
'USER': 'root',
'PASSWORD': 'invalid-password',
'SSH_OPTS': '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
}, {})

self.assertIn('Permission denied, please try again.', stdout)
self.assertFalse(result)
17 changes: 17 additions & 0 deletions tests/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

import inspect
import sys
import os

path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + '/../'
sys.path.append(path)

try:
from .infracheck.infracheck.runner import Runner
except ImportError as e:
from infracheck.infracheck.runner import Runner


def run_check(check_type: str, input_data: dict, hooks: dict):
runner = Runner([path + '/../example/healthchecks', path])
return runner.run(check_type, input_data, hooks)
46 changes: 46 additions & 0 deletions tests/utils/ssh_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

import docker
import docker.errors
import subprocess
import time


class TestThatRequiresSshServer:
docker_client: docker.DockerClient

def setUp(self) -> None:
self.docker_client = docker.from_env()
self._remove_ssh_container()
self.docker_client.containers.run('sickp/alpine-sshd:7.5', name='ssh', ports={'22/tcp': 3222}, detach=True)
self._wait_for_ssh_to_be_ready()

def tearDown(self) -> None:
self._remove_ssh_container()

def _remove_ssh_container(self):
try:
container = self.docker_client.containers.get('ssh')

try:
container.kill()
except docker.errors.APIError:
pass

container.remove()

except docker.errors.NotFound:
pass

@staticmethod
def _wait_for_ssh_to_be_ready():
for i in range(1, 30):
try:
out = subprocess.check_output('echo "ttttt\n\n" | nc -w 1 "localhost" "3222"',
shell=True, stderr=subprocess.STDOUT)

if "SSH-2.0-OpenSSH" in str(out):
return
except subprocess.CalledProcessError:
time.sleep(0.5)

raise Exception('SSH container did not get up properly')

0 comments on commit 5f59478

Please sign in to comment.