OSSubprocess 64-bit macOS Mojave

15 January 2019

OSSubprocess works on macOS Mojave with 64-bit Pharo.

Load it the usual way:

Metacello new
  baseline: 'OSSubprocess';
  repository: 'github://pharo-contributions/OSSubprocess:master/repository';
  load. 

Run the tests. If Pharo was started like how applications are usually started on the Mac, by double-clicking the Pharo.app icon, Test Runner will report 40+ test errors.

Run Pharo the Unix way on the command line: ~/MyApps/Pharo.app/Contents/MacOS/Pharo mypharo7.image. Now all 114 tests pass. All 7 stress tests pass too. Tested with Pharo 7.0 pre-release image.

P3 with Parameter Binding

8 January 2019

Sven Van Caekenberghe has announced a new release of P3, which also implements parameter binding using the PostgreSQL extended query protocol.

Both P3 and PostgresV3 support TLS, the former's being Pharo-specific and the latter's being Squeak-specific.

Which to use? Simple - on Pharo, use P3; on Squeak, use PostgresV3.

PostgresV3 with Parameter Binding

25 December 2018

PostgresV3 is a pure Smalltalk implementation of the PostgreSQL v3 wire protocol. I've modified PostgresV3-Core to do parameter binding and added PostgresV3-DBAPI, a very simple client API.

In PostgresV3-DBAPI, there are a number of examples in PG3ExampleClient. These examples require a PostgreSQL server loaded with the Sakila database. To set that up, firstly, download the Sakila database files. Place the PostgreSQL files in ~/data, say.

The quickest way to get PostgreSQL up and running is by Docker. Here's my docker-compose file that uses the official Postgres-11 image. Data is kept in a separate volume 'pgdata'.

version: '3.6'

services:
  postgres:
    image: postgres:11
    ports:
      - "5432:5432"
    volumes:
      - type: bind
        source: /home/pierce/data
        target: /tmp/data
      - type: volume
        source: pgdata
        target: /var/lib/postgresql/data/datavolume
    environment:
      PGDATA: /var/lib/postgresql/data/datavolume
    restart: unless-stopped

volumes:
  pgdata:
    name: pgdata
    external: true

Bring up PostgreSQL, create roles, load the Sakila data, assign permissions:

% sudo docker-compose up -d
Creating network "postgres-sakila_default" with the default driver
Creating postgres-sakila_postgres_1 ... done

% sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
936cc31523e3        postgres:11         "docker-entrypoint.s…"   36 seconds ago      Up 34 seconds       0.0.0.0:5432->5432/tcp   postgres-sakila_postgres_1

% sudo docker exec -it 936cc31523e3 bash
root@936cc31523e3:/# su - postgres
postgres@936cc31523e3:~$ psql 
psql (11.1 (Debian 11.1-1.pgdg90+1))
Type "help" for help.
postgres=# create role testuser login password 'secret';
CREATE ROLE
postgres=# create database sakila owner testuser;
CREATE DATABASE
postgres=# \c sakila
You are now connected to database "sakila" as user "postgres".
sakila=> \i /tmp/data/postgres-sakila-schema.sql 
...
GRANT
GRANT
sakila=> \i /tmp/data/postgres-sakila-data.sql 
...
COPY 2
ALTER TABLE
sakila=# grant all privileges on all tables in schema public to testuser;
GRANT
sakila=# grant all privileges on all sequences in schema public to testuser;
GRANT
sakila=# \q
postgres@936cc31523e3:~$ logout
root@936cc31523e3:/# exit
%

In a fresh Squeak image - I'm using 5.2 - evaluate in a workspace:

Installer monticello http: 'http://www.squeaksource.com/';
  project: 'PostgresV3';
  install: 'PostgresV3-Core';
  install: 'PostgresV3-Tests-Core';
  install: 'PostgresV3-DBAPI'.

PG3ExampleClient selectSakilaSimple.
PG3ExampleClient selectSakila.
PG3ExampleClient selectSakilaOneStringParam.
PG3ExampleClient selectSakilaOneStringParam2.
PG3ExampleClient selectSakilaOneStringParamNoResult.
PG3ExampleClient selectSakilaOneIntegerParam.
PG3ExampleClient selectSakilaTwoParams.
PG3ExampleClient insertThenSelectSakila.

In a fresh Pharo image - I'm using the latest 7.0 pre-release - evaluate in a playground:

Gofer it 	
  url: 'http://squeaksource.com/PostgresV3';
  package: 'PostgresV3-Core';
  package: 'PostgresV3-Tests-Core';
  package: 'PostgresV3-DBAPI';
  load. 

PG3ExampleClient selectSakilaSimple.
PG3ExampleClient selectSakila.
PG3ExampleClient selectSakilaOneStringParam.
PG3ExampleClient selectSakilaOneStringParam2.
PG3ExampleClient selectSakilaOneStringParamNoResult.
PG3ExampleClient selectSakilaOneIntegerParam.
PG3ExampleClient selectSakilaTwoParams.
PG3ExampleClient insertThenSelectSakila.

As this is a pure Smalltalk implementation, it should also work in earlier versions of Squeak and Pharo.

Testing and comments welcome.

This blog now on HTTPS

9 December 2018

This blog is now on HTTPS.

Setup:

  • Caddy as web reverse proxy.
  • SmallCMS1, the blog engine, runs on Pharo 6.
  • Blog content is held in a Fossil repository with a running Fossil server to support content pushing.
  • Each component runs in a Docker container.

Caddy is an open source HTTP/2 web server. caddy-docker-proxy is a plugin for Caddy enabling Docker integration - when an appropriately configured Docker container or service is brought up, caddy-docker-proxy generates a Caddy site specification entry for it and reloads Caddy. With Caddy's built-in Let's Encrypt functionality, this allows the new container/service to run over HTTPS seamlessly.

Below is my docker-compose.yml for Caddy. I built Caddy with the caddy-docker-proxy plugin from source and named the resulting Docker image samadhiweb/caddy. The Docker network caddynet is the private network for Caddy and the services it is proxying. The Docker volume caddy-data is for persistence of data such as cryptographic keys and certificates.

version: '3.6'

services:

  caddy:
    image: samadhiweb/caddy
    command: -agree -docker-caddyfile-path=/pkg/caddy/caddyfile -log=/var/log/caddy/caddy.log
    ports: 
      - "80:80"
      - "443:443"
    networks: 
      - caddynet
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock
      - type: bind
        source: /pkg/caddy
        target: /pkg/caddy
      - type: volume
        source: caddy-data
        target: /root/.caddy
      - type: bind
        source: /var/log/caddy
        target: /var/log/caddy
    restart: unless-stopped

networks:
  caddynet:
    name: caddynet
    external: true

volumes:
  caddy-data:
    name: caddy-data
    external: true

Here's the docker-compose.yml snippet for the blog engine:

services:
  scms1app:
    image: samadhiweb/scms1app
    ports: 
      - "8081:8081"
    networks:
      - caddynet
    volumes:
      - type: bind
        source: /pkg/smallcms1/config.json
        target: /etc/smallcms1/config.json
      - type: volume
        source: smdw-content
        target: /pkg/cms
    labels:
      - "caddy.address=www.samadhiweb.com"
      - "caddy.targetport=8081"
      - "caddy.targetprotocol=http"
      - "caddy.proxy.header_upstream_1=Host www.samadhiweb.com"
      - "caddy.proxy.header_upstream_2=X-Real-IP {remote}"
      - "caddy.proxy.header_upstream_3=X-Forwarded-For {remote}"
      - "caddy.tls=email-address@samadhiweb.com"
      - "caddy.log=/var/log/caddy/www.samadhiweb.com.access.log"
    ulimits:
      rtprio:
        soft: 2
        hard: 2
    restart: unless-stopped

networks:
  caddynet:
    name: caddynet
    external: true

volumes:
  smdw-content:
    name: smdw-content
    external: true

Of interest are the caddy.* labels from which caddy-docker-proxy generates the following in-memory Caddy site entry:

www.samadhiweb.com {
  log /var/log/caddy/www.samadhiweb.com.access.log
  proxy / http://<private-docker-ip>:8081 {
    header_upstream Host www.samadhiweb.com
    header_upstream X-Real-IP {remote}
    header_upstream X-Forwarded-For {remote}
  }
  tls email-address@samadhiweb.com
}

Also note the ulimits section, which sets the suggested limits for the Pharo VM heartbeat thread. These limits must be set in the docker-compose file or on the docker command line - copying a prepared file into /etc/security/limits.d/pharo.conf does not work when run in a Docker container.

    ulimits:
      rtprio:
        soft: 2
        hard: 2