diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..85e9ea5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.7-alpine as base + +FROM base as builder + +RUN mkdir /install +WORKDIR /install + +COPY requirements.txt /requirements.txt + +RUN pip install --install-option="--prefix=/install" -r /requirements.txt + +FROM base + +COPY --from=builder /install /usr/local +COPY . /bumper + +WORKDIR /bumper + +ENTRYPOINT ["python3", "-m", "bumper"] \ No newline at end of file diff --git a/README.md b/README.md index 4e7d23c..d88b49d 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,44 @@ Bumper has a number of available command-line arguments that can be viewed by ad Bumper looks for a number of Environment Variables at initialization allowing for customizing a number of settings. For more information see the [Environment Variables](docs/Env_Var.md) doc. + +## Docker + +### Docker build + +To build the docker image you can run the following: +`docker build -t bumper .` + +This requires Docker 17.09 or newer, but has also been tested with podman. + +### Docker usage + +To run the image in docker some environment settings and port mappings are required: + +**Ports Required: (-p)** +- 443 - `-p 443:443` +- 8007 - `-p 8007:8007` +- 8883 - `-p 8883:8883` +- 5223 - `-p 5223:5223` + +**Environment Settings: (-e)** + +BUMPER_ANNOUNCE_IP should be used so the actual host IP is reported to bots that checkin. +- BUMPER_ANNOUNCE_IP - `-e "BUMPER_ANNOUNCE_IP=X.X.X.X"` + +**Volume Settings: (-v)** + +Optionally you can map existing directories for logs, data, and certs. + +- data/logs/certs +- Data - `-v /home/user/bumper/data:/bumper/data` + +**Full Example:** + +```` +docker run -it -e "BUMPER_ANNOUNCE_IP=X.X.X.X" -p 443:443 -p 8007:8007 -p 8883:8883 -p 5223:5223 -v /home/user/bumper/data:/bumper/data --name bumper bumper +```` + ## Thanks A big thanks to the original project creator @torbjornaxelsson, without his work this project would have taken much longer to build. diff --git a/bumper/__init__.py b/bumper/__init__.py index 62d083e..c28e6aa 100644 --- a/bumper/__init__.py +++ b/bumper/__init__.py @@ -23,23 +23,29 @@ def strtobool(strbool): # os.environ['PYTHONASYNCIODEBUG'] = '1' # Uncomment to enable ASYNCIODEBUG - bumper_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) -# Set defaults from environment variables first -# Certs -ca_cert = os.environ.get("BUMPER_CA") or os.path.join(bumper_dir, "certs", "ca.crt") -server_cert = os.environ.get("BUMPER_CERT") or os.path.join( - bumper_dir, "certs", "bumper.crt" -) -server_key = os.environ.get("BUMPER_KEY") or os.path.join( - bumper_dir, "certs", "bumper.key" -) +# Set defaults from environment variables first +print(bumper_dir) # Folders logs_dir = os.environ.get("BUMPER_LOGS") or os.path.join(bumper_dir, "logs") os.makedirs(logs_dir, exist_ok=True) # Ensure logs directory exists or create +print(logs_dir) data_dir = os.environ.get("BUMPER_DATA") or os.path.join(bumper_dir, "data") os.makedirs(data_dir, exist_ok=True) # Ensure data directory exists or create +print(data_dir) +certs_dir = os.environ.get("BUMPER_CERTS") or os.path.join(bumper_dir, "certs") +os.makedirs(certs_dir, exist_ok=True) # Ensure data directory exists or create +print(certs_dir) + + +# Certs +ca_cert = os.environ.get("BUMPER_CA") or os.path.join(certs_dir, "ca.crt") +print(ca_cert) +server_cert = os.environ.get("BUMPER_CERT") or os.path.join(certs_dir, "bumper.crt") +print(server_cert) +server_key = os.environ.get("BUMPER_KEY") or os.path.join(certs_dir, "bumper.key") +print(server_key) # Listeners bumper_listen = os.environ.get("BUMPER_LISTEN") or socket.gethostbyname( @@ -113,6 +119,7 @@ xmppserverlog.addHandler(xmpp_rotate) logging.getLogger("asyncio").setLevel(logging.CRITICAL + 1) # Ignore this logger + mqtt_listen_port = 8883 conf1_listen_port = 443 conf2_listen_port = 8007 @@ -163,7 +170,7 @@ async def start(): global conf_server_2 conf_server_2 = ConfServer( (bumper_listen, conf2_listen_port), usessl=False, helperbot=mqtt_helperbot - ) + ) global xmpp_server xmpp_server = XMPPServer((bumper_listen, xmpp_listen_port)) @@ -970,6 +977,7 @@ def create_certs(): subprocess.run([os.path.join("..", "create_certs", "create_certs_linux")]) else: + os.chdir(odir) logging.log( logging.FATAL, "Can't determine platform. Create certs manually and try again.", @@ -988,24 +996,8 @@ def create_certs(): os.execv(sys.executable, ["python"] + sys.argv) # Start again -def firstrun_input(): - return input( - "No certificates found, would you like to create them automatically? (y/n): " - ).lower() - - def first_run(): - yes = {"yes", "y", "ye", ""} - print("") - if firstrun_input() in yes: - create_certs() - - else: - logging.log( - logging.FATAL, - "Can't continue without certificates, please create some then try again.", - ) - + create_certs() def main(argv=None): import argparse diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1727715 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,16 @@ +-i https://pypi.python.org/simple +aiohttp==4.0.0a0 +async-timeout==3.0.1 +attrs==19.1.0 +chardet==3.0.4 +docopt==0.6.2 +hbmqtt==0.9.5 +idna==2.8 +multidict==4.5.2 +passlib==1.7.1 +pyyaml==5.1.1 +six==1.12.0 +tinydb==3.13.0 +transitions==0.6.9 +websockets==7.0 +yarl==1.3.0 diff --git a/tests/test_z_problem.py b/tests/test_z_problem.py index bf93b00..f3f00f2 100644 --- a/tests/test_z_problem.py +++ b/tests/test_z_problem.py @@ -13,29 +13,10 @@ from testfixtures import LogCapture import sys -@patch("bumper.firstrun_input") -@patch("bumper.create_certs") -def test_firstrun(mock_input, mock_create): - with LogCapture() as l: - - bumper.firstrun_input.return_value = "n" - bumper.first_run() - l.check_present( - ( - "root", - "CRITICAL", - "Can't continue without certificates, please create some then try again.", - ) - ) - - bumper.firstrun_input.return_value = "y" - bumper.first_run() - assert mock_create.called == True - - def mock_subrun(*args): return args + @patch("bumper.start") def test_argparse(mock_start): bumper.ca_cert = "tests/test_certs/ca.crt" @@ -70,23 +51,35 @@ def test_createcert(mock_run, mock_platform, mock_machine, mock_exec): platform.system.return_value = "darwin" bumper.create_certs() assert mock_run.called == True - assert os.path.join("..", "create_certs", "create_certs_osx") in mock_exec.call_args.args[0] + assert ( + os.path.join("..", "create_certs", "create_certs_osx") + in mock_exec.call_args.args[0] + ) platform.system.return_value = "windows" bumper.create_certs() assert mock_run.called == True - assert os.path.join("..", "create_certs", "create_certs_windows.exe") in mock_exec.call_args.args[0] + assert ( + os.path.join("..", "create_certs", "create_certs_windows.exe") + in mock_exec.call_args.args[0] + ) platform.system.return_value = "linux" bumper.create_certs() assert mock_run.called == True - assert os.path.join("..", "create_certs","create_certs_linux") in mock_exec.call_args.args[0] + assert ( + os.path.join("..", "create_certs", "create_certs_linux") + in mock_exec.call_args.args[0] + ) platform.system.return_value = "linux" platform.machine.return_value = "arm" bumper.create_certs() assert mock_run.called == True - assert os.path.join("..", "create_certs", "create_certs_rpi") in mock_exec.call_args.args[0] + assert ( + os.path.join("..", "create_certs", "create_certs_rpi") + in mock_exec.call_args.args[0] + ) with LogCapture() as l: platform.system.return_value = "nixbad" @@ -101,7 +94,6 @@ def test_createcert(mock_run, mock_platform, mock_machine, mock_exec): ) - @patch("bumper.first_run") def test_main(mock_firstrun): bumper.ca_cert = "sf"