Skip to content
This repository was archived by the owner on Dec 8, 2024. It is now read-only.

Commit a285c8d

Browse files
author
Dan Breakiron
committed
Removed requirement to install terminal_sync; updated Dockerfile
- Updated Dockerfile to export requirements.txt (to ensure platform compatibility) and install using pip rather than PDM (to reduce runtime complexity) - Increased minimum Python version to 3.10 due to use of PEP-604 style type hinting syntax - Reduced default timeout values as the previous ones were painfully long if something failed and would negatively impact user experience - Minor updates to the README - Updated CHANGELOG
1 parent 6130be1 commit a285c8d

13 files changed

+79
-35
lines changed

CHANGELOG.md

+18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [v0.2.0] - 2023-04-26
9+
10+
### Added
11+
12+
- Added a new feature to save failed (or optionally all) logs locally (as JSON files)
13+
- Created a script / library to export the JSON files to a GhostWriter CSV
14+
- Configured the server to automatically export a CSV file on shutdown (though stopping a Docker container doesn't seem to trigger it)
15+
16+
### Fixed
17+
18+
- Fixed several syntax errors in the Bash install / hook script that prevented successful installation
19+
20+
### Changed
21+
22+
- Updated Dockerfile to export requirements.txt (to ensure platform compatibility) and install using pip rather than PDM (to reduce runtime complexity)
23+
- Increased minimum Python version to 3.10 due to use of PEP-604 style type hinting syntax
24+
- Reduced default timeout values as the previous ones were painfully long if something failed and would negatively impact user experience
25+
826
## [v0.1.0] - 2023-04-21
927

1028
Initial release

Dockerfile

+25-16
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,43 @@
1-
FROM python:3.11
1+
# Install PDM and use it to export requirements.txt to ensure platform compatibility
2+
FROM python:3.11-slim as requirements-stage
23

3-
ENV LANG=C.UTF-8
4+
WORKDIR /tmp
5+
6+
RUN pip install pdm
7+
8+
# Copy the pyproject.toml and pdm.lock files to the /tmp directory
9+
# Because it uses ./pdm.lock* (ending with a *), it won't crash if that file is not available
10+
COPY ./pyproject.toml ./pdm.lock* /tmp/
11+
12+
# Generate requirements.txt
13+
RUN pdm export --prod --without-hashes -o requirements.txt
14+
15+
# Build the final image
16+
FROM python:3.11-slim
17+
18+
# ENV LANG=C.UTF-8 # Defined in the base image
419
ENV LC_ALL=C.UTF-8
520
ENV LC_TIME=C.UTF-8
621
ENV LISTEN_PORT=8000
722
# Enable Python optimizations
823
ENV PYTHONOPTIMIZE=1
924

10-
# Create a directory where cached log entries will be stored
11-
# VOLUME /app/log_archive
12-
1325
WORKDIR /app
1426

15-
# COPY requirements.txt requirements.txt
16-
17-
# RUN pip install --no-cache-dir --upgrade -r requirements.txt
18-
19-
# COPY ./src/terminal_sync .
20-
21-
RUN pip install pdm
27+
# Copy the requirements.txt file from the previous stage
28+
COPY --from=requirements-stage /tmp/requirements.txt /app/requirements.txt
2229

23-
COPY . .
30+
# Upgrade pip and install / upgrade required packages
31+
RUN pip install --no-cache-dir --upgrade pip && pip install --no-cache-dir --upgrade -r requirements.txt
2432

25-
RUN pdm install --prod
33+
# Copy the application code into the container
34+
COPY ./src/terminal_sync ./terminal_sync
2635

2736
EXPOSE $LISTEN_PORT/tcp
2837

2938
# FastAPI has a built-in /docs endpoint that we can use to check whether the server is running properly
3039
HEALTHCHECK CMD curl --fail http://localhost:$LISTEN_PORT/docs || exit 1
3140

41+
# Run terminal_sync as a module
3242
# IMPORTANT: This must listen on 0.0.0.0 or else the application will not be accessible outside of the container
33-
CMD pdm run uvicorn terminal_sync.api:app --host 0.0.0.0 --port $LISTEN_PORT
34-
# CMD ["pdm", "run", "uvicorn", "terminal_sync.api:app", "--host", "0.0.0.0", "--port", $LISTEN_PORT]
43+
CMD python3 -m terminal_sync --host 0.0.0.0 --port $LISTEN_PORT

README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ For the purpose of this documentation, the terms "API key" and "token" are used
7474
- Bash
7575

7676
1. Edit the **Configuration Settings** section at the top of `terminal_sync.sh`
77-
2. Run `chmod +x ./terminal_sync.sh && ./terminal_sync.sh`
77+
2. Run `source ./terminal_sync.sh`
7878
- **Note**: This must be done in each new bash session
7979
- You will be prompted to install any missing dependencies
8080
- On first run, you will also be prompted whether you want to install the hooks permanently
8181

82-
- If you want to install the hooks later, just append `source <PATH_TO>/terminal_sync.sh` to your `~/.bashrc` file.
82+
- If you want to install the hooks later, just append `source '<PATH_TO>/terminal_sync.sh'` to your `~/.bashrc` file.
8383

8484
- PowerShell
8585

@@ -139,7 +139,7 @@ To permanently disable terminal_sync, delete or comment out the line in `~/.bash
139139

140140
Both the Bash script and PowerShell module contain a configuration setting that allows you to set the default console output. If you want to (temporarily) change this for a session, use one of the following commands.
141141

142-
In Bash, run `set_termsync_versbosity`; this will print a list of display settings and prompt you for a number. Simply enter the number that matches your preferred setting.
142+
In Bash, run `Set-TermSyncVersbosity`; this will print a list of display settings and prompt you for a number. Simply enter the number that matches your preferred setting.
143143

144144
In PowerShell, type `Set-TermSyncVerbosity`, followed by a space, then press **TAB** to cycle through the available options. Press **Enter** to select your preferred setting.
145145

@@ -165,6 +165,8 @@ Development and testing were performed using the following configurations. If yo
165165
- Docker Compose v2.17.2
166166
- PowerShell 5.1.22621.963
167167
- Python 3.11
168+
- Debian 11 (terminal_sync server and Bash hooks)
169+
- Python 3.11.3
168170
- Debian 11 (Bash hooks)
169171
- Python 3.9.2
170172
- GhostWriter running over HTTPS

pdm.lock

+1-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ build-backend = "pdm.backend"
44

55
[project]
66
name = "terminal_sync"
7-
version = "0.1.0"
7+
version = "0.2.0"
88
description = "A standalone tool for logging shell commands to GhostWriter automatically"
99
authors = [{ name = "breakid" }]
1010
license = { text = "GPL-3.0-or-later" }
1111
readme = "README.md"
12-
requires-python = ">=3.8"
12+
requires-python = ">=3.10" # The type hinting used in this project follows PEP 604, which was implemented in 3.10
1313
dependencies = [
1414
"aiohttp>=3.8.4",
1515
"fastapi>=0.95.0",

src/terminal_sync/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
"""Marks the current directory as a Python package"""
2+
3+
# Note: Version is also defined in pyproject.toml. Ideally, to ensure they don't get out of sync, version would
4+
# only be defined once; however, the project one is only accessible if terminal_sync is installed as a package
5+
__version__ = "0.2.0"

src/terminal_sync/__main__.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
"""Executes the terminal_sync server when the module is run"""
2+
3+
# Standard Libraries
4+
from argparse import ArgumentParser
5+
26
# Internal Libraries
37
from terminal_sync.api import run
48

5-
run()
9+
parser = ArgumentParser()
10+
parser.add_argument("--host", dest="host", default="127.0.0.1", help="The host address where the server will bind")
11+
parser.add_argument("--port", dest="port", default=8000, type=int, help="The host port where the server will bind")
12+
args = parser.parse_args()
13+
14+
run(host=args.host, port=args.port)

src/terminal_sync/api.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ async def post_exec(msg: Message) -> str:
271271
async def app_shutdown() -> None:
272272
"""Export a GhostWriter CSV file on server shutdown"""
273273
try:
274-
csv_filepath: Path = export_csv(Path(config.termsync_json_log_dir))
274+
csv_filepath: Path = export_csv(Path(config.termsync_json_log_dir), Path(config.termsync_json_log_dir))
275275
logger.info(f"Exported cached logs to: {csv_filepath}")
276276
except Exception as e:
277277
logger.exception(e)

src/terminal_sync/config.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class Config:
5151
termsync_listen_host: str = "127.0.0.1"
5252
termsync_listen_port: int = 8000
5353
termsync_save_all_local: bool = False
54-
termsync_timeout_seconds: int = 10
54+
termsync_timeout_seconds: int = 3
5555

5656
# TODO: Automatically add keywords "exported" by registered command parsers
5757
# TODO: This list should only contain keywords that don't have an associated command parser

src/terminal_sync/config_template.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ termsync_keywords:
4545
#termsync_save_all_local: no
4646

4747
# The number of seconds the server will wait for a response from GhostWriter
48-
#termsync_timeout_seconds: 10
48+
#termsync_timeout_seconds: 3

src/terminal_sync/ghostwriter.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22

33
# Standard Libraries
44
import logging
5-
6-
# from asyncio.exceptions import TimeoutError
75
from collections.abc import Callable
8-
from importlib import metadata
96

107
# Third-party Libraries
118
import aiohttp
@@ -15,6 +12,7 @@
1512
from gql.transport.aiohttp import AIOHTTPTransport
1613

1714
# Internal Libraries
15+
from terminal_sync import __version__ as termsync_version
1816
from terminal_sync.log_entry import Entry
1917

2018
logger = logging.getLogger("terminal_sync")
@@ -113,7 +111,7 @@ def __init__(self, url: str, graphql_api_key: str = "", rest_api_key: str = "",
113111
self.base_url: str = url.rstrip("/")
114112

115113
self.headers: dict[str, str] = {
116-
"User-Agent": f"terminal_sync/{metadata.version('terminal_sync')}",
114+
"User-Agent": f"terminal_sync/{termsync_version}",
117115
"Authorization": f"Bearer {graphql_api_key}" if graphql_api_key else f"Api-Key {rest_api_key}",
118116
"Content-Type": "application/json",
119117
}
@@ -123,9 +121,15 @@ def __init__(self, url: str, graphql_api_key: str = "", rest_api_key: str = "",
123121
self.update_log: Callable = self._update_entry_graphql
124122

125123
if graphql_api_key:
124+
logger.info("Using the GraphQL API")
126125
url = f"{self.base_url}/v1/graphql"
127-
self._transport: AIOHTTPTransport = AIOHTTPTransport(url=url, timeout=timeout_seconds, headers=self.headers)
126+
# WORKAROUND: When running Docker on a Windows host, the application will always hang waiting for the SSL
127+
# connection to terminate. The ssl_close_timeout is therefore set to 0 to avoid a negative user experience
128+
self._transport: AIOHTTPTransport = AIOHTTPTransport(
129+
url=url, headers=self.headers, ssl_close_timeout=0, timeout=timeout_seconds
130+
)
128131
else:
132+
logger.info("Using the REST API")
129133
# Important: If you leave off the trailing "/" on oplog/api/entries/ then this POST will return "200 OK"
130134
# without actually doing anything
131135
self.rest_url: str = f"{self.base_url}/oplog/api/entries/"

terminal_sync.psm1

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ $global:TermSyncVerbosity = 4
2020
$global:TermSyncServer = "127.0.0.1:8000"
2121

2222
# The number of seconds the client will wait for a response from the terminal_sync server
23-
$global:TimeoutSec = 10
23+
$global:TimeoutSec = 4
2424

2525

2626
# =============================================================================

terminal_sync.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ TERMSYNC_LOGGING=1
1414
TERMSYNC_VERBOSITY=4
1515

1616
# The number of seconds the client will wait for a response from the terminal_sync server
17-
TERMSYNC_TIMEOUT=10
17+
TERMSYNC_TIMEOUT=4
1818

1919

2020
# =============================================================================

0 commit comments

Comments
 (0)