Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docker-compose.printer.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: '2'
services:
sce-printer:
container_name: sce-printer-dev
build:
context: .
dockerfile: ./printer/Dockerfile.printer.dev
ports:
# we use port 14000 as that is what the website expects
# the printing server to be running on
- 14000:14000
volumes:
- ./config:/app/config
- ./printer:/app/printer
- ./tmp:/tmp
command:
- --development
- --port=14000
- --dont-delete-pdfs
- --config-json-path=/app/config/config.json
23 changes: 23 additions & 0 deletions printer/Dockerfile.printer.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Base image from https://github.com/DrPsychick/docker-cups-airprint
# Docker images are here https://hub.docker.com/r/drpsychick/airprint-bridge/tags
FROM drpsychick/airprint-bridge:jammy

WORKDIR /app

RUN apt-get update

RUN apt install -y python3 python3-pip python3-venv

# Create the virtual environment with Python
RUN python3 -m venv /opt/venv

# Set the virtual environment as the default Python environment
ENV PATH="/opt/venv/bin:$PATH"

COPY ./printer/requirements.txt /app/printer/requirements.txt

RUN /opt/venv/bin/pip install -r /app/printer/requirements.txt

EXPOSE 9000

ENTRYPOINT ["./printer/what_dev.sh"]
13 changes: 11 additions & 2 deletions printer/modules/gerard.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import logging
import shlex
import subprocess

import datetime

LP_COMMAND = """
lp \
-H {hold_time} \
-n {num_copies} {maybe_page_range} \
-o sides={sides} \
-o media=na_letter_8.5x11in \
Expand Down Expand Up @@ -36,16 +37,23 @@ def __next__(self):

print_job_suffix = IDIterator()


def create_print_job(
num_copies,
maybe_page_range,
sides,
printer_name,
file_path,
is_development_mode=False,
# no_dev_printer=False
):
hold_time = "immediate"
if is_development_mode:
future_datetime = datetime.datetime.fromtimestamp(datetime.datetime.utcnow().timestamp() + 5)
hold_time = f"{future_datetime.hour}:{future_datetime.minute}:{future_datetime.second}"


command = LP_COMMAND.format(
hold_time=hold_time,
num_copies=num_copies,
maybe_page_range=maybe_page_range,
sides=sides,
Expand All @@ -59,6 +67,7 @@ def create_print_job(
)
job_id = f"HP_LaserJet_p2015dn_Right-{next(print_job_suffix)}"
return job_id


args_list = shlex.split(command.strip())
logging.info(f"running command {command}")
Expand Down
17 changes: 17 additions & 0 deletions printer/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import threading
import time
import uuid
import sqlite3

from fastapi import FastAPI, File, Form, HTTPException, UploadFile
from fastapi.middleware.cors import CORSMiddleware
Expand Down Expand Up @@ -63,6 +64,7 @@ def get_args() -> argparse.Namespace:
default=False,
help="specify if server should run in development. this means requests won't get sent to a printer but logger instead",
)

parser.add_argument(
"--dont-delete-pdfs",
action="store_true",
Expand Down Expand Up @@ -119,6 +121,10 @@ def send_file_to_printer(

# only the right printer works right now, so we default to it
PRINTER_NAME = os.environ.get("RIGHT_PRINTER_NAME")

if (args.development):
PRINTER_NAME = "HP_LaserJet_p2015dn_Right"

metrics_handler.print_jobs_recieved.inc()

job_id = gerard.create_print_job(
Expand Down Expand Up @@ -148,6 +154,17 @@ def api():
def metrics():
return prometheus_client.generate_latest()

@app.get("/status/")
async def status(id: str = ''):
try:
db = sqlite3.connect(args.database_file_path)
cursor = db.cursor()
cursor.execute(f"SELECT status FROM logs WHERE job_id = ?", (id,))
status = cursor.fetchone()[0]
return {"status": status}
except Exception:
logging.exception("failed to get status of job with id: " + id)
return {"status": "failed"}

@app.post("/print")
async def read_item(
Expand Down
9 changes: 6 additions & 3 deletions printer/test/test_gerard.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def test_create_print_job(self, mock_popen):
mock_popen.call_args_list[0],
mock.call(
shlex.split(gerard.LP_COMMAND.format(
hold_time="immediate",
num_copies=1,
maybe_page_range="1",
sides="one-side",
Expand Down Expand Up @@ -76,6 +77,7 @@ def test_create_print_job_nonzero_returncode(self, mock_popen):
mock_popen.call_args_list[0],
mock.call(
shlex.split(gerard.LP_COMMAND.format(
hold_time="immediate",
num_copies=1,
maybe_page_range="",
sides="dark-side",
Expand Down Expand Up @@ -113,6 +115,7 @@ def test_create_print_job_cant_parse_stdout(self, mock_popen):
mock_popen.call_args_list[0],
mock.call(
shlex.split(gerard.LP_COMMAND.format(
hold_time="immediate",
num_copies=1,
maybe_page_range="1",
sides="one-side",
Expand All @@ -129,19 +132,19 @@ def test_create_print_job_cant_parse_development_mode(self):

self.assertEqual(
gerard.create_print_job(
1, "1", "one-side", "HP_P2015_DN", "/tmp/test-id", True
1, "1", "one-side", "HP_P2015_DN", "/tmp/test-id", True,
),
"HP_LaserJet_p2015dn_Right-0",
)
self.assertEqual(
gerard.create_print_job(
1, "1", "one-side", "HP_P2015_DN", "/tmp/test-id", True
1, "1", "one-side", "HP_P2015_DN", "/tmp/test-id", True,
),
"HP_LaserJet_p2015dn_Right-1",
)
self.assertEqual(
gerard.create_print_job(
1, "1", "one-side", "HP_P2015_DN", "/tmp/test-id", True
1, "1", "one-side", "HP_P2015_DN", "/tmp/test-id", True,
),
"HP_LaserJet_p2015dn_Right-2",
)
Expand Down
4 changes: 4 additions & 0 deletions printer/test/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def test_print_endpoint(self, mock_pathlib_unlink, mock_open_func, mock_popen, _
mock_popen.call_args_list[0],
mock.call(
shlex.split(gerard.LP_COMMAND.format(
hold_time="immediate",
num_copies=1,
maybe_page_range="",
sides="one-sided",
Expand Down Expand Up @@ -137,6 +138,7 @@ def test_print_endpoint_dont_delete_pdf(
mock_popen.call_args_list[0],
mock.call(
shlex.split(gerard.LP_COMMAND.format(
hold_time="immediate",
num_copies=1,
maybe_page_range="",
sides="one-sided",
Expand Down Expand Up @@ -221,6 +223,7 @@ def test_print_endpoint_nonzero_returncode(
mock_popen.call_args_list[0],
mock.call(
shlex.split(gerard.LP_COMMAND.format(
hold_time="immediate",
num_copies=1,
maybe_page_range="",
sides="dark-side",
Expand Down Expand Up @@ -275,6 +278,7 @@ def test_junk_print_id(self, mock_pathlib_unlink, mock_open_func, mock_popen, _)
mock_popen.call_args_list[0],
mock.call(
shlex.split(gerard.LP_COMMAND.format(
hold_time="immediate",
num_copies=1,
maybe_page_range="",
sides="one-sided",
Expand Down
12 changes: 12 additions & 0 deletions printer/what_dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

# MAKE SURE THIS FILE IS USING LF FOR ITS EOL SEQUENCE!!!!!!!!!!!
# OTHERWISE DOCKER WILL COMPLAIN THAT THIS FILE DOESNT EXIST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

/root/start-cups.sh > /dev/null 2>&1 &

sleep 10

lpadmin -p HP_LaserJet_p2015dn_Right -E -v file:///dev/null

python3 /app/printer/server.py $@