Docker #46
5 changed files with 110 additions and 53 deletions
19
Dockerfile
Normal file
19
Dockerfile
Normal file
|
|
@ -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"]
|
||||||
38
README.md
38
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.
|
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
|
## Thanks
|
||||||
|
|
||||||
A big thanks to the original project creator @torbjornaxelsson, without his work this project would have taken much longer to build.
|
A big thanks to the original project creator @torbjornaxelsson, without his work this project would have taken much longer to build.
|
||||||
|
|
|
||||||
|
|
@ -23,23 +23,29 @@ def strtobool(strbool):
|
||||||
|
|
||||||
|
|
||||||
# os.environ['PYTHONASYNCIODEBUG'] = '1' # Uncomment to enable ASYNCIODEBUG
|
# os.environ['PYTHONASYNCIODEBUG'] = '1' # Uncomment to enable ASYNCIODEBUG
|
||||||
|
|
||||||
bumper_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
|
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
|
# Folders
|
||||||
logs_dir = os.environ.get("BUMPER_LOGS") or os.path.join(bumper_dir, "logs")
|
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
|
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")
|
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
|
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
|
# Listeners
|
||||||
bumper_listen = os.environ.get("BUMPER_LISTEN") or socket.gethostbyname(
|
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
|
logging.getLogger("asyncio").setLevel(logging.CRITICAL + 1) # Ignore this logger
|
||||||
|
|
||||||
|
|
||||||
mqtt_listen_port = 8883
|
mqtt_listen_port = 8883
|
||||||
conf1_listen_port = 443
|
conf1_listen_port = 443
|
||||||
conf2_listen_port = 8007
|
conf2_listen_port = 8007
|
||||||
|
|
@ -970,6 +977,7 @@ def create_certs():
|
||||||
subprocess.run([os.path.join("..", "create_certs", "create_certs_linux")])
|
subprocess.run([os.path.join("..", "create_certs", "create_certs_linux")])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
os.chdir(odir)
|
||||||
logging.log(
|
logging.log(
|
||||||
logging.FATAL,
|
logging.FATAL,
|
||||||
"Can't determine platform. Create certs manually and try again.",
|
"Can't determine platform. Create certs manually and try again.",
|
||||||
|
|
@ -988,25 +996,9 @@ def create_certs():
|
||||||
os.execv(sys.executable, ["python"] + sys.argv) # Start again
|
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():
|
def first_run():
|
||||||
yes = {"yes", "y", "ye", ""}
|
|
||||||
print("")
|
|
||||||
if firstrun_input() in yes:
|
|
||||||
create_certs()
|
create_certs()
|
||||||
|
|
||||||
else:
|
|
||||||
logging.log(
|
|
||||||
logging.FATAL,
|
|
||||||
"Can't continue without certificates, please create some then try again.",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv=None):
|
def main(argv=None):
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
|
|
||||||
16
requirements.txt
Normal file
16
requirements.txt
Normal file
|
|
@ -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
|
||||||
|
|
@ -13,29 +13,10 @@ from testfixtures import LogCapture
|
||||||
import sys
|
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):
|
def mock_subrun(*args):
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
@patch("bumper.start")
|
@patch("bumper.start")
|
||||||
def test_argparse(mock_start):
|
def test_argparse(mock_start):
|
||||||
bumper.ca_cert = "tests/test_certs/ca.crt"
|
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"
|
platform.system.return_value = "darwin"
|
||||||
bumper.create_certs()
|
bumper.create_certs()
|
||||||
assert mock_run.called == True
|
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"
|
platform.system.return_value = "windows"
|
||||||
bumper.create_certs()
|
bumper.create_certs()
|
||||||
assert mock_run.called == True
|
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"
|
platform.system.return_value = "linux"
|
||||||
bumper.create_certs()
|
bumper.create_certs()
|
||||||
assert mock_run.called == True
|
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.system.return_value = "linux"
|
||||||
platform.machine.return_value = "arm"
|
platform.machine.return_value = "arm"
|
||||||
bumper.create_certs()
|
bumper.create_certs()
|
||||||
assert mock_run.called == True
|
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:
|
with LogCapture() as l:
|
||||||
platform.system.return_value = "nixbad"
|
platform.system.return_value = "nixbad"
|
||||||
|
|
@ -101,7 +94,6 @@ def test_createcert(mock_run, mock_platform, mock_machine, mock_exec):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@patch("bumper.first_run")
|
@patch("bumper.first_run")
|
||||||
def test_main(mock_firstrun):
|
def test_main(mock_firstrun):
|
||||||
bumper.ca_cert = "sf"
|
bumper.ca_cert = "sf"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue