Skip to content

Commit

Permalink
fix: docker-compose file decoding (#184)
Browse files Browse the repository at this point in the history
* adjust snapshots...

* fix: suport new docker-compose port format , add decode step and update to latest docker-compose file format

* update snapshots
  • Loading branch information
n1ru4l authored Oct 22, 2020
1 parent 9f32613 commit 23a5d87
Show file tree
Hide file tree
Showing 25 changed files with 150 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ yarn add dockest --dev
```yml
# docker-compose.yml

version: '3.7'
version: '3.8'

services:
myRedis:
Expand Down
6 changes: 3 additions & 3 deletions docs/api_reference_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ will ensure that `service1` starts up and is fully responsive before even attemp
[Docker's docs](https://docs.docker.com/compose/compose-file/#depends_on) explains this very neatly:

```yaml
version: '3.7'
version: '3.8'
services:
web:
build: .
Expand Down Expand Up @@ -130,7 +130,7 @@ The default readiness check for PostgreSQL is based on this [image](https://hub.

```yaml
# docker-compose.yml
version: '3.7'
version: '3.8'
services:
postgres: # (1)
Expand Down Expand Up @@ -169,7 +169,7 @@ The default readiness check for Redis is based on this [image](https://hub.docke

```yaml
# docker-compose.yml
version: '3.7'
version: '3.8'
services:
redis: # (1)
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ The next step is to transform this unit test into an integration test by creatin
```yml
# docker-compose.yml

version: '3.7'
version: '3.8'

services:
myRedis:
Expand Down
2 changes: 1 addition & 1 deletion packages/dockest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ yarn add dockest --dev
```yml
# docker-compose.yml

version: '3.7'
version: '3.8'

services:
myRedis:
Expand Down
2 changes: 2 additions & 0 deletions packages/dockest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
},
"dependencies": {
"chalk": "^3.0.0",
"io-ts": "^2.2.10",
"fp-ts": "^2.8.3",
"execa": "^4.0.0",
"is-docker": "^2.0.0",
"js-yaml": "^3.13.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('getParsedComposeFile', () => {
],
},
},
"version": "3.7",
"version": "3.8",
}
`)
})
Expand Down
77 changes: 72 additions & 5 deletions packages/dockest/src/run/bootstrap/getParsedComposeFile.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,84 @@
import { safeLoad } from 'js-yaml'
import * as io from 'io-ts'
import { PathReporter } from 'io-ts/lib/PathReporter'
import * as Either from 'fp-ts/lib/Either'
import { pipe, identity, flow } from 'fp-ts/lib/function'
import { DockerComposeFile } from '../../@types'
import { DockestError } from '../../Errors'
import { Logger } from '../../Logger'

export const getParsedComposeFile = (mergedComposeFiles: string) => {
const dockerComposeFile: DockerComposeFile = safeLoad(mergedComposeFiles)
const PortBinding = io.type({
published: io.number,
target: io.number,
})

const PortBindingFromString = new io.Type(
'PortBindingFromComposeString',
PortBinding.is,
(input: string, context) => {
const match = input.match(/(\d*):(\d*)\/\w*/)
return match
? io.success({
target: parseInt(match[2], 10),
published: parseInt(match[1], 10),
})
: io.failure(input, context, 'String did not match expected format.')
},
identity,
)
const PortBindingFromComposeFile = new io.Type(
'PortBindingFromComposeFile',
PortBinding.is,
(input, context) =>
pipe(
io.string.is(input) ? PortBindingFromString.validate(input, context) : PortBinding.validate(input, context),
Either.fold(
err =>
io.failure(
input,
context,
'Could not decode the port mappings. This is most likely related to a breaking change in the docker-compose format.\n' +
`Received: ${JSON.stringify(input)}\n` +
err
.filter(err => err.message)
.map(err => `- ${err.message}`)
.join('\n') +
'Please report this issue on the dockest issue tracker: https://github.com/erikengervall/dockest/issues',
),
binding => io.success(binding),
),
),
identity,
)

const DockerComposeService = io.type({
ports: io.array(PortBindingFromComposeFile),
})

const ComposeFile = io.type({
version: io.string,
services: io.record(io.string, DockerComposeService),
})

const handleDecodeError = (err: io.Errors) => {
const lines = PathReporter.report(Either.left(err))
throw new DockestError('Invalid schema. \n' + lines.map(line => `- ${line}`).join('\n'))
}

const decodeComposeFile = flow(ComposeFile.decode, Either.fold(handleDecodeError, identity))
const DOCKEST_COMPOSE_FILE_VERSION = '3.8'

export const getParsedComposeFile = (mergedComposeFiles: string): { dockerComposeFile: DockerComposeFile } => {
const dockerComposeFile = pipe(mergedComposeFiles, safeLoad, decodeComposeFile)

const versionNumber = parseFloat(dockerComposeFile.version)
if (Math.trunc(versionNumber) < 3) {
throw new DockestError(`Incompatible docker-compose file version. Please use version '3.x'`)
} else if (versionNumber !== 3.7) {
Logger.warn(`You should upgrade to docker-compose file version '3.7'. Dockest automatically uses that version`)
dockerComposeFile.version = '3.7'
} else if (dockerComposeFile.version !== DOCKEST_COMPOSE_FILE_VERSION) {
Logger.warn(
`You should upgrade to docker-compose file version '${DOCKEST_COMPOSE_FILE_VERSION}'. Dockest automatically uses that version.`,
)
dockerComposeFile.version = DOCKEST_COMPOSE_FILE_VERSION
}

return {
Expand Down
13 changes: 8 additions & 5 deletions packages/dockest/src/run/bootstrap/mergeComposeFiles.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ describe('mergeComposeFiles', () => {
redis:
image: redis:5.0.3-alpine
ports:
- published: 6379
- protocol: tcp
published: 6379
target: 6379
version: '3.7'
version: '3.8'
"
`)
})
Expand All @@ -37,14 +38,16 @@ describe('mergeComposeFiles', () => {
POSTGRES_USER: ramda
image: postgres:9.6-alpine
ports:
- published: 5433
- protocol: tcp
published: 5433
target: 5432
redis:
image: redis:5.0.3-alpine
ports:
- published: 6379
- protocol: tcp
published: 6379
target: 6379
version: '3.7'
version: '3.8'
"
`)
})
Expand Down
5 changes: 2 additions & 3 deletions packages/dockest/src/run/bootstrap/mergeComposeFiles.spec.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
version: '3.7'
version: '3.8'

services:
redis:
image: redis:5.0.3-alpine
ports:
- published: 6379
target: 6379
- 6379:6379/tcp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3.8'

services:
postgres:
Expand All @@ -8,5 +8,4 @@ services:
POSTGRES_USER: ramda
image: postgres:9.6-alpine
ports:
- published: 5433
target: 5432
- 5433:5432/tcp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DockestService, DockerComposeFile } from '../../@types'

const serviceName = 'service1'
const dockerComposeFile: DockerComposeFile = {
version: '3.7',
version: '3.8',
services: {
[serviceName]: { ports: [{ published: 3000, target: 3000 }] },
},
Expand Down
4 changes: 2 additions & 2 deletions packages/dockest/src/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const DOCKEST_SERVICE: DockestService = {
}

export const DOCKER_COMPOSE_FILE: DockerComposeFile = {
version: '3.7',
version: '3.8',
services: {
[DOCKEST_SERVICE.serviceName]: {
image: 'redis:5.0.3-alpine',
Expand All @@ -40,5 +40,5 @@ services:
ports:
- published: 6379
target: 6379
version: '3.7'
version: '3.8'
`
10 changes: 10 additions & 0 deletions packages/dockest/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,11 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"

fp-ts@^2.8.3:
version "2.8.3"
resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.8.3.tgz#c09652bbf21e64d65a9f93587ad549ab0e03abe7"
integrity sha512-oGD3BTSzFCPs9alaI/2gh0SCNKyhPXkpeIBvkXNvnoczHfDAUd2HHtotCdLO0hOTTTTx8VKA0mhhR7LUNo+cKg==

fragment-cache@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
Expand Down Expand Up @@ -1496,6 +1501,11 @@ inherits@2:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==

io-ts@^2.2.10:
version "2.2.10"
resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.10.tgz#447d02df51717464a90712b146ec8dbc21b4a74b"
integrity sha512-WHx5jJe7hPpc6JoSIVbD+Xn6tYqe3cRvNpX24d8Wi15/kxhRWa8apo0Gzag6Xg99sCNY9OHKylw/Vhv0JAbNPQ==

ip-regex@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
Expand Down
24 changes: 24 additions & 0 deletions packages/examples/aws-codebuild/src/CI.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM node:12-slim

LABEL author="Laurin Quast <laurinquast@googlemail.com>"

ENV DOCKER_COMPOSE_VERSION="1.27.4"
ENV DOCKER_BUILD_X_VERSION="0.4.2"

RUN apt-get update \
&& apt-get install -y python3 curl bash apt-transport-https ca-certificates software-properties-common gnupg2 jq \
&& curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
&& python3 get-pip.py \
&& rm get-pip.py \
&& curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - \
&& add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" \
&& apt-get update \
&& apt-get install -y docker-ce docker-ce-cli containerd.io \
\
&& pip install "docker-compose==$DOCKER_COMPOSE_VERSION" \
&& docker-compose version \
\
&& mkdir -p ~/.docker/cli-plugins \
&& curl -fsSL "https://github.com/docker/buildx/releases/download/v$DOCKER_BUILD_X_VERSION/buildx-v$DOCKER_BUILD_X_VERSION.linux-amd64" --output ~/.docker/cli-plugins/docker-buildx \
&& chmod a+x ~/.docker/cli-plugins/docker-buildx && \
echo "done."
4 changes: 2 additions & 2 deletions packages/examples/aws-codebuild/src/buildspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ phases:
commands:
# docker in docker integration
- nohup /usr/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&
- timeout -t 15 sh -c "until docker info; do echo .; sleep 1; done"
- yarn
- timeout 15 sh -c "until docker info; do echo .; sleep 1; done"
- yarn install --no-lockfile

build:
commands:
Expand Down
6 changes: 4 additions & 2 deletions packages/examples/aws-codebuild/src/codebuild_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ set -euxo pipefail
echo "Run dockest as usual"
yarn test:codebuild:buildspec

# image source: https://github.com/n1ru4l/docker-image-node-10-with-docker-and-compose
echo "Build docker image"
docker build --file CI.Dockerfile -t aws-codebuild-ci-node .

echo "Run dockest inside the codebuild container"
./codebuild_build.sh -i n1ru4l/aws-codebuild-node:7712cfae8d65fd3b704f74e84f688739de5bd357 -a .artifacts
./codebuild_build.sh -i aws-codebuild-ci-node -a .artifacts
2 changes: 1 addition & 1 deletion packages/examples/aws-codebuild/src/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3.8'

services:
aws_codebuild_website:
Expand Down
8 changes: 4 additions & 4 deletions packages/examples/docker-in-docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
FROM docker:19.03.8-dind

ARG DOCKER_COMPOSE_VERSION="1.25.4"
ARG DOCKER_BUILDX_VERSION="v0.3.1"
ARG NODE_JS_VERSION="12.16.1"
ARG YARN_VERSION="1.22.4"
ARG DOCKER_COMPOSE_VERSION="1.27.4"
ARG DOCKER_BUILDX_VERSION="v0.4.2"
ARG NODE_JS_VERSION="12.18.4"
ARG YARN_VERSION="1.22.10"

RUN apk add --no-cache curl bash

Expand Down
2 changes: 1 addition & 1 deletion packages/examples/docker-in-docker/src/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3.8'

services:
docker_in_docker_website:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3.8'

services:
multiple_compose_files_postgres:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3.8'

services:
multiple_compose_files_redis:
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/multiple-resources/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3.8'

services:
multiple_resources_postgres1sequelize:
Expand Down
2 changes: 1 addition & 1 deletion packages/examples/node-to-node/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.7'
version: '3.8'

services:
node_to_node_orders:
Expand Down
6 changes: 3 additions & 3 deletions website/versioned_docs/version-2.0.0/api_reference_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ will ensure that `service1` starts up and is fully responsive before even attemp
[Docker's docs](https://docs.docker.com/compose/compose-file/#depends_on) explains this very neatly:

```yaml
version: '3.7'
version: '3.8'
services:
web:
build: .
Expand Down Expand Up @@ -131,7 +131,7 @@ The default readiness check for PostgreSQL is based on this [image](https://hub.

```yaml
# docker-compose.yml
version: '3.7'
version: '3.8'
services:
postgres: # (1)
Expand Down Expand Up @@ -170,7 +170,7 @@ The default readiness check for Redis is based on this [image](https://hub.docke

```yaml
# docker-compose.yml
version: '3.7'
version: '3.8'
services:
redis: # (1)
Expand Down
Loading

0 comments on commit 23a5d87

Please sign in to comment.