version: '3.7'
services:
  # We run integration_test.go from this container, it connects to the other mox instances.
  test:
    hostname: test.mox1.example
    image: mox_integration_test
    # We add our cfssl-generated CA (which is in the repo) and acme pebble CA
    # (generated each time pebble starts) to the list of trusted CA's, so the TLS
    # dials in integration_test.go succeed.
    command: ["sh", "-c", "set -ex; cat /integration/tmp-pebble-ca.pem /integration/tls/ca.pem >>/etc/ssl/certs/ca-certificates.crt; go test -tags integration"]
    volumes:
      - ./.go:/.go
      - ./testdata/integration/resolv.conf:/etc/resolv.conf
      - ./testdata/integration:/integration
      - ./testdata/integration/moxsubmit.conf:/etc/moxsubmit.conf
      - .:/mox
    environment:
      GOCACHE: /.go/.cache/go-build
    depends_on:
      dns:
        condition: service_healthy
      # moxmail2 depends on moxacmepebble, we connect to both.
      moxmail2:
        condition: service_healthy
      postfixmail:
        condition: service_healthy
      localserve:
        condition: service_healthy
    networks:
      mailnet1:
        ipv4_address: 172.28.1.50

  # First mox instance that uses ACME with pebble.
  moxacmepebble:
    hostname: moxacmepebble.mox1.example
    domainname: mox1.example
    image: mox_integration_moxmail
    environment:
      MOX_UID: "${MOX_UID}"
    command: ["sh", "-c", "/integration/moxacmepebble.sh"]
    volumes:
      - ./testdata/integration/resolv.conf:/etc/resolv.conf
      - ./testdata/integration:/integration
    healthcheck:
      test: netstat -nlt | grep ':25 '
      interval: 1s
      timeout: 1s
      retries: 10
    depends_on:
      dns:
        condition: service_healthy
      acmepebble:
        condition: service_healthy
    networks:
      mailnet1:
        ipv4_address: 172.28.1.10

  # Second mox instance, with TLS cert/keys from files.
  moxmail2:
    hostname: moxmail2.mox2.example
    domainname: mox2.example
    image: mox_integration_moxmail
    environment:
      MOX_UID: "${MOX_UID}"
    command: ["sh", "-c", "/integration/moxmail2.sh"]
    volumes:
      - ./testdata/integration/resolv.conf:/etc/resolv.conf
      - ./testdata/integration:/integration
    healthcheck:
      test: netstat -nlt | grep ':25 '
      interval: 1s
      timeout: 1s
      retries: 10
    depends_on:
      dns:
        condition: service_healthy
      acmepebble:
        condition: service_healthy
      # moxacmepebble creates tmp-pebble-ca.pem, needed by moxmail2 to trust the certificates offered by moxacmepebble.
      moxacmepebble:
        condition: service_healthy
    networks:
      mailnet1:
        ipv4_address: 172.28.1.20

  localserve:
    hostname: localserve.mox1.example
    domainname: mox1.example
    image: mox_integration_moxmail
    command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; mox -checkconsistency localserve -ip 172.28.1.60"]
    volumes:
      - ./.go:/.go
      - ./testdata/integration/resolv.conf:/etc/resolv.conf
      - .:/mox
    environment:
      GOCACHE: /.go/.cache/go-build
    healthcheck:
      test: netstat -nlt | grep ':1025 '
      interval: 1s
      timeout: 1s
      retries: 10
    depends_on:
      dns:
        condition: service_healthy
    networks:
      mailnet1:
        ipv4_address: 172.28.1.60

  postfixmail:
    hostname: postfixmail.postfix.example
    domainname: postfix.example
    build:
      dockerfile: Dockerfile.postfix
      context: testdata/integration
    volumes:
      # todo: figure out how to mount files with a uid that the process in the container can read...
      - ./testdata/integration/resolv.conf:/etc/resolv.conf
    command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; (echo 'maillog_file = /dev/stdout'; echo 'mydestination = $$myhostname, localhost.$$mydomain, localhost, $$mydomain'; echo 'smtp_tls_security_level = may') >>/etc/postfix/main.cf; echo 'root: postfix@mox1.example' >>/etc/postfix/aliases; newaliases; postfix start-fg"]
    healthcheck:
      test: netstat -nlt | grep ':25 '
      interval: 1s
      timeout: 1s
      retries: 10
    depends_on:
      dns:
        condition: service_healthy
    networks:
      mailnet1:
        ipv4_address: 172.28.1.70

  dns:
    hostname: dns.example
    build:
      dockerfile: Dockerfile.dns
      # todo: figure out how to build from dockerfile with empty context without creating empty dirs in file system.
      context: testdata/integration
    volumes:
      - ./testdata/integration/resolv.conf:/etc/resolv.conf
      - ./testdata/integration:/integration
    # We start with a base example.zone, but moxacmepebble appends its records,
    # followed by moxmail2. They restart unbound after appending records.
    command: ["sh", "-c", "set -ex; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; install -m 640 -o unbound /integration/unbound.conf /etc/unbound/; chmod 755 /integration; chmod 644 /integration/*.zone; cp /integration/example.zone /integration/example-integration.zone; ls -ld /integration /integration/reverse.zone; unbound -d -p -v"]
    healthcheck:
      test: netstat -nlu | grep '172.28.1.30:53 '
      interval: 1s
      timeout: 1s
      retries: 10
    networks:
      mailnet1:
        ipv4_address: 172.28.1.30

  # pebble is a small acme server useful for testing. It creates a new CA
  # certificate each time it starts, so we go through some trouble to configure the
  # certificate in moxacmepebble and moxmail2.
  acmepebble:
    hostname: acmepebble.example
    image: docker.io/letsencrypt/pebble:v2.3.1@sha256:fc5a537bf8fbc7cc63aa24ec3142283aa9b6ba54529f86eb8ff31fbde7c5b258
    volumes:
      - ./testdata/integration/resolv.conf:/etc/resolv.conf
      - ./testdata/integration:/integration
    command: ["sh", "-c", "set -ex; mount; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; pebble -config /integration/pebble-config.json"]
    ports:
      - 14000:14000  # ACME port
      - 15000:15000  # Management port
    healthcheck:
      test: netstat -nlt | grep ':14000 '
      interval: 1s
      timeout: 1s
      retries: 10
    depends_on:
      dns:
        condition: service_healthy
    networks:
      mailnet1:
        ipv4_address: 172.28.1.40

networks:
  mailnet1:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: "172.28.1.0/24"