Skip to content

Commit 5621877

Browse files
Merge branch 'refactoring-for-extension' into 'main'
Base docker image off ucbears See merge request lap/sftp_handler!8
2 parents a0ee3a6 + 67e6ecb commit 5621877

7 files changed

Lines changed: 153 additions & 44 deletions

File tree

.gitignore

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
# Convoluted gitkeep setting to keep the data directory
2-
# structure intact without tracking its contents.
1+
# secrets file
2+
.env
33

44
vendor
55
.bundle
66

7+
# Convoluted gitkeep setting to keep the data directory
8+
# structure intact without tracking its contents.
79
data/*
810
!data/.keep
911

1012
# Build/test artifacts
1113
artifacts/*
12-
13-
secrets/*
14-
!secrets/.keep

Dockerfile

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,95 @@
1-
#FROM debian:bullseye-slim
2-
FROM ruby:3.0
3-
USER root
1+
# =============================================================================
2+
# Target: base
3+
#
4+
# The base stage scaffolds elements which are common to building and running
5+
# the application, such as installing ca-certificates, creating the app user,
6+
# and installing runtime system dependencies.
7+
FROM ruby:3.0.3-slim AS base
8+
9+
# ------------------------------------------------------------
10+
# Create the application user/group and installation directory
11+
12+
# UCBEARS uses the "altmedia" user and group because (historical/permissions) reasons
13+
ENV APP_USER=alma
14+
ENV APP_UID=40054
15+
16+
RUN groupadd --system --gid $APP_UID $APP_USER \
17+
&& useradd --home-dir /opt/app --system --uid $APP_UID --gid $APP_USER $APP_USER
18+
19+
RUN mkdir -p /opt/app \
20+
&& chown -R $APP_USER:$APP_USER /opt/app /usr/local/bundle
421

5-
RUN apt-get update
22+
# ------------------------------------------------------------
23+
# Install packages common to dev and prod.
624

7-
# Create the application user/group and application directory
8-
RUN groupadd -g 40054 alma && \
9-
useradd -r -s /sbin/nologin -M -u 40054 -g alma alma && \
10-
mkdir -p /opt/app && \
11-
chown -R alma:alma /opt/app
25+
# Install standard packages from the Debian repository
26+
RUN apt-get update -qq
1227

13-
# Run everything else as the alma user
28+
# ------------------------------------------------------------
29+
# Run configuration
30+
31+
# All subsequent commands are executed relative to this directory.
1432
WORKDIR /opt/app
1533

16-
COPY --chown=alma Gemfile* ./
17-
RUN bundle install --system
18-
COPY --chown=alma . .
34+
# Run as the application user to minimize risk to the host.
35+
USER $APP_USER
1936

20-
USER alma
37+
# Uses the get_gobi script as the entrypoint, so any arguments passed to `docker run`
38+
# at invocation are passed directly to this script.
2139
ENTRYPOINT ["ruby","/opt/app/lib/get_gobi.rb"]
22-
#CMD ["help"]
40+
41+
# =============================================================================
42+
# Target: development
43+
#
44+
# The development stage installs build dependencies (system packages needed to
45+
# install all your gems) along with your bundle. It's "heavier" than the
46+
# production target.
47+
FROM base AS development
48+
49+
# ------------------------------------------------------------
50+
# Install build packages
51+
52+
# Temporarily switch back to root
53+
USER root
54+
55+
# Install system packages needed to build gems with C extensions.
56+
RUN apt-get install -y --no-install-recommends \
57+
g++ \
58+
git \
59+
make
60+
61+
# ------------------------------------------------------------
62+
# Install Ruby gems
63+
64+
# Drop back to $APP_USER.
65+
USER $APP_USER
66+
67+
# Base image ships with an older version of bundler
68+
RUN gem install bundler --version 2.2.33
69+
70+
# Install gems. We don't enforce the validity of the Gemfile.lock until the
71+
# final (production) stage.
72+
COPY --chown=$APP_USER:$APP_USER Gemfile* ./
73+
RUN bundle install
74+
75+
# Copy the rest of the codebase. We do this after bundle-install so that
76+
# changes unrelated to the gemset don't invalidate the cache and force a slow
77+
# re-install.
78+
COPY --chown=$APP_USER:$APP_USER . .
79+
80+
# =============================================================================
81+
# Target: production
82+
#
83+
# The production stage extends the base image with the application and gemset
84+
# built in the development stage. It includes runtime dependencies (including
85+
# test dependencies, due to quirks of our Jenkins build) but tries to minimize
86+
# heavyweight build dependencies.
87+
FROM base AS production
88+
89+
# Copy the built codebase from the dev stage
90+
COPY --from=development --chown=$APP_USER /opt/app /opt/app
91+
COPY --from=development --chown=$APP_USER /usr/local/bundle /usr/local/bundle
92+
93+
# Ensure the bundle is installed and the Gemfile.lock is synced.
94+
RUN bundle config set frozen 'true'
95+
RUN bundle install --local

Gemfile.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ GEM
1111
diff-lcs (1.5.0)
1212
erb (2.2.3)
1313
cgi
14+
getoptlong (0.1.1)
1415
hashdiff (1.0.1)
1516
net-sftp (3.0.0)
1617
net-ssh (>= 5.0.0, < 7.0.0)
@@ -35,6 +36,8 @@ GEM
3536
diff-lcs (>= 1.2.0, < 2.0)
3637
rspec-support (~> 3.11.0)
3738
rspec-support (3.11.0)
39+
rspec_junit_formatter (0.5.1)
40+
rspec-core (>= 2, < 4, != 2.12.0)
3841
rubocop (1.26.0)
3942
parallel (~> 1.10)
4043
parser (>= 3.1.0.0)
@@ -46,6 +49,8 @@ GEM
4649
unicode-display_width (>= 1.4.0, < 3.0)
4750
rubocop-ast (1.16.0)
4851
parser (>= 3.1.1.0)
52+
rubocop-checkstyle_formatter (0.5.0)
53+
rubocop (>= 1.14.0)
4954
ruby-progressbar (1.11.0)
5055
thor (1.2.1)
5156
unicode-display_width (2.1.0)
@@ -61,9 +66,12 @@ PLATFORMS
6166
DEPENDENCIES
6267
colorize
6368
erb
69+
getoptlong
6470
net-sftp
6571
rspec
72+
rspec_junit_formatter
6673
rubocop
74+
rubocop-checkstyle_formatter
6775
thor (~> 1.1)
6876
uri
6977
webmock

README.md

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,70 @@
11
# GOBI Processor
2-
A command-line tool for retrieving GOBI order marc files (.ord) via sftp. Default remote directory is gobiord and local directory is data.
32

4-
## Building the app
3+
A command-line tool for retrieving GOBI order marc files (.ord) via sftp.
54

6-
```sh
7-
docker-compose build
5+
## Running it locally
6+
7+
To run the application for real, you'll need to configure a local `.env` file with the GOBI password, which you can obtain from LastPass (search for "gobi"). Don't worry: this file is git-ignored.
8+
9+
```ini
10+
# ./.env (in the directory you cloned this from GitLab)
11+
GOBI_PASS=password-from-lastpass
812
```
913

10-
## Running it locally
14+
---
15+
16+
> **Additional Configuration:** The app accepts a few other configuration options, which you can see in `config/connections.yml`. The default values should work fine, however, so you probably don't need to change them. Also note that everything is mocked in the rspec tests, where you're not actually hitting the GOBI server.
1117
12-
Look for todays Gobi order file will be name eboo{mmdd}.ord on the gobi server in the gobiord directory.
13-
File by default will go into /opt/app/data directory
18+
---
19+
20+
With that configured, you can run the application like so:
1421

1522
```sh
16-
docker-compose up
23+
docker compose build # as always, you need to build it first
24+
docker compose run --rm app ebook0413.ord
1725
```
1826

19-
Look for a specific file
27+
Today's GOBI order file will be at `/gobiord/eboo{mmdd}.ord` on their server. By default, the app copies it into the `/opt/app/data` directory within the container (mapped to `./data` in development), but this can be overwritten by the `--local_dir` flag:
2028

2129
```sh
22-
docker-compose run --rm gobi_sftp ebook0413.ord
30+
docker compose run --rm app --local_dir /path/in/container
2331
```
2432

25-
Look for a specific file with command line arguments
33+
Look for a specific file by passing its name as an argument:
2634

2735
```sh
28-
docker-compose run --rm gobi_sftp ebook0413.ord --remote_dir gobiord local_dir path_to_local_dir
36+
docker-compose run --rm app ebook0413.ord
2937
```
3038

39+
You can also pass additional arguments when looking for a specific file:
3140

32-
## Running it in production
41+
```sh
42+
docker-compose run --rm app ebook0413.ord \
43+
--remote_dir gobiord-staging \
44+
--local_dir path_to_local_dir
45+
```
46+
47+
## Testing
3348

34-
Standard way this should be set to run each day to look for a file if it exists
49+
The app includes a number of RSpec tests integrated into its Jenkins pipeline. You can run the tests locally via:
3550

3651
```sh
37-
docker run --rm gobi_sftp --local_dir '/path_to_local_dir'
52+
docker compose run --rm --entrypoint=rspec app
3853
```
3954

40-
Example if you wanted to specify a specific remote directory as well
55+
Or by shelling into the container and running RSpec from there:
4156

4257
```sh
43-
docker run --rm gobi_sftp ebook0312.ord --remote_dir remote_directory --local_dir '/path_to_local_dir'
58+
docker compose run --rm --entrypoint=sh app
59+
rspec
4460
```
61+
62+
---
63+
64+
> **Insecure KEX:** As of 04/28/22, Gobi's server only supports outdated Diffie-Hellman key exchange algorithms, which you local sftp client will probably (and correctly) refuse. If you want to test manually, then for now you must explicitly allow the old algorithm by passing the following option to your sftp client: `-oKexAlgorithms=+diffie-hellman-group1-sha1`.
65+
66+
---
67+
68+
## Production configuration
69+
70+
In production, the app must copy the files to a place accessible to Alma, which is configured to pull them daily at 9PM. As of 04/28/22, this was decided to be the `gobi-ebook-eocr` directory in the `alma` NetApp volume.

config/connections.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
gobi:
2-
host: <%= ENV['GOBI_HOST'] %>
3-
user: <%= ENV['GOBI_USER'] %>
4-
password: <%= ENV['GOBI_PASS'] %>
2+
host: <%= ENV.fetch('GOBI_HOST', 'ftp.ybp.com') %>
3+
user: <%= ENV.fetch('GOBI_USER', 'berkeley') %>
4+
password: <%= ENV.fetch('GOBI_PASS', 'p4$$w0r6') %>

docker-compose.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
services:
2-
gobi_sftp:
3-
build: .
2+
app:
3+
build:
4+
context: .
5+
target: development
6+
environment:
7+
GOBI_PASS: "${GOBI_PASS}"
48
image: containers.lib.berkeley.edu/lap/gobi_sftp/development:latest
59
init: yes
610
volumes:
7-
- ./:/opt/app:rw
8-
- ./secrets:/run/secrets
11+
- ./:/opt/app
912

1013
version: "3.8"

secrets/.keep

Whitespace-only changes.

0 commit comments

Comments
 (0)