23 Commits

Author SHA1 Message Date
b83efda648 test(assets): add depends_on as example
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-25 18:21:07 +01:00
5dea30fec0 fix(domain): iterate when merging over custom configs
The normal dcmerge did not work, as the check and addition was only
possible if at least one attribute such as service, network or volume
was presentThe normal dcmerge did not work, as the check and addition
was only possible if at least one attribute such as service, network or
volume was present.

The logic was adjusted.

The logic was adjusted.
2023-11-25 18:21:07 +01:00
3d97ee0ab8 fix(lint): increase line length to 120 2023-11-25 18:21:07 +01:00
8b68c9587c feat: support depends_on 2023-11-25 18:21:07 +01:00
669ebd0f25 chore(deps): update docker.io/plugins/docker docker tag to v20.17.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-11-15 14:07:06 +00:00
8f794494a2 chore(deps): update docker.io/library/golang docker tag to v1.21.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-11-07 23:05:08 +00:00
8e411cc486 chore(deps): update module github.com/spf13/cobra to v1.8.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-11-05 23:24:28 +01:00
d7e8970860 Merge pull request 'chore(deps): update docker.io/plugins/docker docker tag to v20.17.0' (#1) from renovate/docker.io-plugins-docker-20.x into master
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-31 02:06:11 +00:00
8603eca0b5 chore(deps): update docker.io/plugins/docker docker tag to v20.17.0
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2023-10-30 23:05:33 +00:00
d8ada5578b fix(ci): unsupport arm v7
All checks were successful
continuous-integration/drone/push Build is passing
2023-10-30 21:32:36 +01:00
4f5d115926 chore(deps): update docker.io/library/golang docker tag to v1.21.3
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-10-11 07:49:22 +02:00
dac3be4e2d chore(deps): update docker.io/library/golang docker tag to v1.21.2
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-10-06 20:32:36 +02:00
173637693f chore(deps): update git.cryptic.systems/volker.raschek/drone-email docker tag to v0.1.5
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-10-03 19:18:35 +02:00
3ba641aa12 chore(deps): update git.cryptic.systems/volker.raschek/git docker tag to v1.3.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-10-03 10:27:29 +02:00
768a49319d chore(deps): update quay.io/skopeo/stable docker tag to v1.13.3
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-09-29 00:38:35 +02:00
66f5fff92a chore(deps): update docker.io/library/alpine docker tag to v3.18.4
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-09-29 00:15:33 +02:00
b6b2e069cd chore(deps): update git.cryptic.systems/volker.raschek/markdownlint docker tag to v0.37.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-09-22 19:33:41 +02:00
2c738d0417 chore(deps): update docker.io/library/golang docker tag to v1.21.1
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-09-06 21:31:18 +02:00
46dd067b48 fix(renovate): exclude updating docker.io/plugins/docker
All checks were successful
continuous-integration/drone/push Build is passing
2023-09-03 16:37:08 +02:00
9669685997 chore(deps): update git.cryptic.systems/volker.raschek/markdownlint docker tag to v0.36.0
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-09-03 13:52:59 +02:00
9a76f3432a chore(deps): update quay.io/skopeo/stable docker tag to v1.13.2
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2023-08-29 22:02:10 +02:00
751bb810d2 fix(dockerCompose): protect of empty attributes 2023-08-28 11:37:24 +02:00
9b469bd8c6 fix: rename firstWin to existingWin 2023-08-28 11:13:32 +02:00
13 changed files with 459 additions and 410 deletions

View File

@ -11,12 +11,12 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: markdown lint
commands:
- markdownlint *.md
image: git.cryptic.systems/volker.raschek/markdownlint:0.35.0
image: git.cryptic.systems/volker.raschek/markdownlint:0.37.0
resources:
limits:
cpu: 150
@ -34,7 +34,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
@ -62,46 +62,18 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: unit-test
commands:
- go test -v ./...
image: docker.io/library/golang:1.21.0
image: docker.io/library/golang:1.21.4
trigger:
event:
exclude:
- tag
---
kind: pipeline
type: docker
name: unit-test-arm-v7
clone:
disable: true
platform:
arch: arm
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
- name: unit-test
commands:
- go test -v ./...
image: docker.io/library/golang:1.21.0
trigger:
event:
include:
- pull_request
- push
exclude:
- tag
---
kind: pipeline
type: docker
@ -115,12 +87,12 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: unit-test
commands:
- go test -v ./...
image: docker.io/library/golang:1.21.0
image: docker.io/library/golang:1.21.4
trigger:
event:
@ -148,10 +120,10 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build
image: docker.io/plugins/docker:20.10.9
image: docker.io/plugins/docker:20.17.1
settings:
auto_tag: false
dockerfile: Dockerfile
@ -181,74 +153,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
when:
status:
- changed
- failure
trigger:
branch:
exclude:
- master
event:
- pull_request
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: dry-run-arm-v7
clone:
disable: true
depends_on:
- linter
- unit-test-arm-v7
platform:
os: linux
arch: arm
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
- name: build
image: docker.io/plugins/docker:20.10.9
settings:
auto_tag: false
dockerfile: Dockerfile
dry_run: true
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
tags: latest-arm-v7
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
@ -282,10 +187,10 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build
image: docker.io/plugins/docker:20.10.9
image: docker.io/plugins/docker:20.17.1
settings:
auto_tag: false
dockerfile: Dockerfile
@ -315,7 +220,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
@ -349,10 +254,10 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build
image: docker.io/plugins/docker:20.10.9
image: docker.io/plugins/docker:20.17.1
settings:
auto_tag: false
dockerfile: Dockerfile
@ -381,72 +286,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
when:
status:
- changed
- failure
trigger:
branch:
- master
event:
- cron
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: latest-arm-v7
clone:
disable: true
depends_on:
- linter
- unit-test-arm-v7
platform:
os: linux
arch: arm
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
- name: build
image: docker.io/plugins/docker:20.10.9
settings:
auto_tag: false
dockerfile: Dockerfile
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
tags: latest-arm-v7
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
@ -479,10 +319,10 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build
image: docker.io/plugins/docker:20.10.9
image: docker.io/plugins/docker:20.17.1
settings:
auto_tag: false
dockerfile: Dockerfile
@ -511,7 +351,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
@ -536,7 +376,6 @@ clone:
depends_on:
- latest-amd64
- latest-arm-v7
- latest-arm64-v8
# docker.io/plugins/manifest only for amd64 architectures available
@ -546,7 +385,7 @@ node_selector:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build-manifest
image: docker.io/plugins/manifest:1.4.0
@ -571,7 +410,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
@ -603,7 +442,7 @@ depends_on:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: latest-sync
commands:
@ -617,7 +456,7 @@ steps:
from_secret: container_image_registry_user
DEST_CRED_PASSWORD:
from_secret: container_image_registry_password
image: quay.io/skopeo/stable:v1.13.1
image: quay.io/skopeo/stable:v1.13.3
- name: email-notification
environment:
@ -631,7 +470,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
@ -664,10 +503,10 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build
image: docker.io/plugins/docker:20.10.9
image: docker.io/plugins/docker:20.17.1
settings:
auto_tag: true
auto_tag_suffix: amd64
@ -698,67 +537,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
when:
status:
- changed
- failure
trigger:
event:
- tag
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: tagged-arm-v7
clone:
disable: true
platform:
os: linux
arch: arm
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
- name: build
image: docker.io/plugins/docker:20.10.9
settings:
auto_tag: true
auto_tag_suffix: arm-v7
dockerfile: Dockerfile
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
build_args:
- VERSION=${DRONE_TAG}
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
@ -784,10 +563,10 @@ platform:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build
image: docker.io/plugins/docker:20.10.9
image: docker.io/plugins/docker:20.17.1
settings:
auto_tag: true
auto_tag_suffix: arm64-v8
@ -818,7 +597,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
@ -840,7 +619,6 @@ clone:
depends_on:
- tagged-amd64
- tagged-arm-v7
- tagged-arm64-v8
# docker.io/plugins/manifest only for amd64 architectures available
@ -850,7 +628,7 @@ node_selector:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: build-manifest
image: docker.io/plugins/manifest:1.4.0
@ -875,7 +653,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
@ -904,7 +682,7 @@ depends_on:
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.2.1
image: git.cryptic.systems/volker.raschek/git:1.3.1
- name: tagged-sync
commands:
@ -918,7 +696,7 @@ steps:
from_secret: container_image_registry_user
DEST_CRED_PASSWORD:
from_secret: container_image_registry_password
image: quay.io/skopeo/stable:v1.13.1
image: quay.io/skopeo/stable:v1.13.3
- name: email-notification
environment:
@ -932,7 +710,7 @@ steps:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.2
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150

View File

@ -45,11 +45,11 @@ MD012:
# MD013/line-length - Line length
MD013:
# Number of characters
line_length: 80
line_length: 120
# Number of characters for headings
heading_line_length: 80
heading_line_length: 120
# Number of characters for code blocks
code_block_line_length: 80
code_block_line_length: 120
# Include code blocks
code_blocks: false
# Include tables

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"rewrap.wrappingColumn": 120,
}

View File

@ -1,4 +1,4 @@
FROM docker.io/library/golang:1.21.0-alpine3.18 AS build
FROM docker.io/library/golang:1.21.4-alpine3.18 AS build
RUN apk add git make
@ -10,7 +10,7 @@ RUN make install \
PREFIX=/usr \
VERSION=${VERSION}
FROM docker.io/library/alpine:3.18.3
FROM docker.io/library/alpine:3.18.4
COPY --from=build /cache /

View File

@ -3,22 +3,18 @@
[![Build Status](https://drone.cryptic.systems/api/badges/volker.raschek/dcmerge/status.svg)](https://drone.cryptic.systems/volker.raschek/dcmerge)
[![Docker Pulls](https://img.shields.io/docker/pulls/volkerraschek/dcmerge)](https://hub.docker.com/r/volkerraschek/dcmerge)
`dcmerge` is a small program to merge docker-compose files from multiple
sources. It is available via RPM and docker.
`dcmerge` is a small program to merge docker-compose files from multiple sources. It is available via RPM and docker.
The dynamic pattern of a docker-compose file, that for example `environments`
can be specified as a string slice or a list of objects is currently not
supported. `dcmerge` expect a strict pattern layout. The `environments`, `ports`
and `volumes` must be declared as a slice of strings.
The dynamic pattern of a docker-compose file, that for example `environments` can be specified as a string slice or a
list of objects is currently not supported. `dcmerge` expect a strict pattern layout. The `environments`, `ports` and
`volumes` must be declared as a slice of strings.
Dockercompose file can be read-in from different sources. Currently are the
following sources supported:
Dockercompose file can be read-in from different sources. Currently are the following sources supported:
- File
- HTTP/HTTPS
Furthermore, `dcmerge` support different ways to merge multiple docker-compose
files.
Furthermore, `dcmerge` support different ways to merge multiple docker-compose files.
- The default merge, add missing secrets, services, networks and volumes.
- The existing-win merge, add and protect existing attributes.
@ -26,9 +22,8 @@ files.
## default
Merge only missing secrets, services, networks and volumes without respecting
their attributes. For example, when the service `app` is already declared, it is
not possible to add the service `app` twice. The second service will be
Merge only missing secrets, services, networks and volumes **without respecting their attributes**. For example, when
the service `app` is already declared, it is not possible to add the service `app` twice. The second service will be
completely skipped.
```yaml
@ -68,10 +63,9 @@ services:
## existing-win
The existing-win merge protects existing attributes. For example there are two
different docker-compose files, but booth has the same environment variable
`CLIENT_SECRET` defined with different values. The first declaration of the
attribute wins and is for overwriting protected.
The existing-win merge protects existing attributes. For example there are two different docker-compose files, but booth
has the same environment variable `CLIENT_SECRET` defined with different values. The first declaration of the attribute
wins and is for overwriting protected.
```yaml
---
@ -99,9 +93,8 @@ services:
## last-win
The last-win merge overwrite recursive existing attributes. For example there
are two different docker-compose files, but booth has the same environment
variable `CLIENT_SECRET` defined with different values. The last passed
The last-win merge overwrite recursive existing attributes. For example there are two different docker-compose files,
but booth has the same environment variable `CLIENT_SECRET` defined with different values. The last passed
docker-compose file which contains this environment wins.
```yaml

View File

@ -42,7 +42,7 @@ dcmerge docker-compose.yml https://git.example.local/user/repo/docker-compose.ym
RunE: run,
Version: version,
}
rootCmd.Flags().BoolP("first-win", "f", false, "Add only missing attributes")
rootCmd.Flags().BoolP("existing-win", "f", false, "Protect existing attributes")
rootCmd.Flags().BoolP("last-win", "l", false, "Overwrite existing attributes")
rootCmd.Flags().StringP("output-file", "o", "", "Write instead on stdout into a file")
rootCmd.AddCommand(completionCmd)
@ -51,7 +51,7 @@ dcmerge docker-compose.yml https://git.example.local/user/repo/docker-compose.ym
}
func run(cmd *cobra.Command, args []string) error {
mergeFirstWin, err := cmd.Flags().GetBool("first-win")
mergeExisting, err := cmd.Flags().GetBool("existing-win")
if err != nil {
return fmt.Errorf("Failed to parse flag last-win: %s", err)
}
@ -75,11 +75,11 @@ func run(cmd *cobra.Command, args []string) error {
for _, config := range dockerComposeConfigs {
switch {
case mergeFirstWin && mergeLastWin:
case mergeExisting && mergeLastWin:
return fmt.Errorf("Neither --first-win or --last-win can be specified - not booth.")
case mergeFirstWin && !mergeLastWin:
dockerComposeConfig.MergeFirstWin(config)
case !mergeFirstWin && mergeLastWin:
case mergeExisting && !mergeLastWin:
dockerComposeConfig.MergeExistingWin(config)
case !mergeExisting && mergeLastWin:
dockerComposeConfig.MergeLastWin(config)
default:
dockerComposeConfig.Merge(config)

2
go.mod
View File

@ -3,7 +3,7 @@ module git.cryptic.systems/volker.raschek/dcmerge
go 1.20
require (
github.com/spf13/cobra v1.7.0
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.4
gopkg.in/yaml.v2 v2.4.0
)

6
go.sum
View File

@ -1,4 +1,4 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@ -6,8 +6,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=

View File

@ -12,12 +12,6 @@ manifests:
platform:
architecture: amd64
os: linux
-
image: git.cryptic.systems/volker.raschek/dcmerge:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}-arm-v7
platform:
architecture: arm
os: linux
variant: v7
-
image: git.cryptic.systems/volker.raschek/dcmerge:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}-arm64-v8
platform:

View File

@ -66,25 +66,25 @@ func (c *Config) ExistsVolume(name string) bool {
// Merge adds only a missing network, secret, service and volume.
func (c *Config) Merge(config *Config) {
for name, network := range c.Networks {
for name, network := range config.Networks {
if !c.ExistsNetwork(name) {
c.Networks[name] = network
}
}
for name, secret := range c.Secrets {
for name, secret := range config.Secrets {
if !c.ExistsSecret(name) {
c.Secrets[name] = secret
}
}
for name, service := range c.Services {
for name, service := range config.Services {
if !c.ExistsService(name) {
c.Services[name] = service
}
}
for name, volume := range c.Volumes {
for name, volume := range config.Volumes {
if !c.ExistsVolume(name) {
c.Volumes[name] = volume
}
@ -92,7 +92,7 @@ func (c *Config) Merge(config *Config) {
}
// MergeLastWin merges a config and overwrite already existing properties
func (c *Config) MergeFirstWin(config *Config) {
func (c *Config) MergeExistingWin(config *Config) {
switch {
case c == nil && config == nil:
fallthrough
@ -108,11 +108,11 @@ func (c *Config) MergeFirstWin(config *Config) {
// fallthrough
default:
c.mergeFirstWinNetworks(config.Networks)
c.mergeFirstWinSecrets(config.Secrets)
c.mergeFirstWinServices(config.Services)
c.mergeFirstWinVersion(config.Version)
c.mergeFirstWinVolumes(config.Volumes)
c.mergeExistingWinNetworks(config.Networks)
c.mergeExistingWinSecrets(config.Secrets)
c.mergeExistingWinServices(config.Services)
c.mergeExistingWinVersion(config.Version)
c.mergeExistingWinVolumes(config.Volumes)
}
}
@ -141,62 +141,62 @@ func (c *Config) MergeLastWin(config *Config) {
}
}
func (c *Config) mergeFirstWinVersion(version string) {
func (c *Config) mergeExistingWinVersion(version string) {
if len(c.Version) <= 0 {
c.Version = version
}
}
func (c *Config) mergeFirstWinNetworks(networks map[string]*Network) {
func (c *Config) mergeExistingWinNetworks(networks map[string]*Network) {
for networkName, network := range networks {
if network == nil {
continue
}
if c.ExistsNetwork(networkName) {
c.Networks[networkName].MergeFirstWin(network)
c.Networks[networkName].MergeExistingWin(network)
} else {
c.Networks[networkName] = network
}
}
}
func (c *Config) mergeFirstWinSecrets(secrets map[string]*Secret) {
func (c *Config) mergeExistingWinSecrets(secrets map[string]*Secret) {
for secretName, secret := range secrets {
if secret == nil {
continue
}
if c.ExistsNetwork(secretName) {
c.Secrets[secretName].MergeFirstWin(secret)
c.Secrets[secretName].MergeExistingWin(secret)
} else {
c.Secrets[secretName] = secret
}
}
}
func (c *Config) mergeFirstWinServices(services map[string]*Service) {
func (c *Config) mergeExistingWinServices(services map[string]*Service) {
for serviceName, service := range services {
if service == nil {
continue
}
if c.ExistsService(serviceName) {
c.Services[serviceName].MergeFirstWin(service)
c.Services[serviceName].MergeExistingWin(service)
} else {
c.Services[serviceName] = service
}
}
}
func (c *Config) mergeFirstWinVolumes(volumes map[string]*Volume) {
func (c *Config) mergeExistingWinVolumes(volumes map[string]*Volume) {
for volumeName, volume := range volumes {
if volume == nil {
continue
}
if c.ExistsNetwork(volumeName) {
c.Volumes[volumeName].MergeFirstWin(volume)
c.Volumes[volumeName].MergeExistingWin(volume)
} else {
c.Volumes[volumeName] = volume
}
@ -301,7 +301,7 @@ func (n *Network) Equal(equalable Equalable) bool {
}
}
func (n *Network) MergeFirstWin(network *Network) {
func (n *Network) MergeExistingWin(network *Network) {
switch {
case n == nil && network == nil:
fallthrough
@ -317,7 +317,7 @@ func (n *Network) MergeFirstWin(network *Network) {
// fallthrough
default:
n.mergeFirstWinIPAM(network.IPAM)
n.mergeExistingWinIPAM(network.IPAM)
}
}
@ -341,9 +341,9 @@ func (n *Network) MergeLastWin(network *Network) {
}
}
func (n *Network) mergeFirstWinIPAM(networkIPAM *NetworkIPAM) {
func (n *Network) mergeExistingWinIPAM(networkIPAM *NetworkIPAM) {
if !n.IPAM.Equal(networkIPAM) {
n.IPAM.MergeFirstWin(networkIPAM)
n.IPAM.MergeExistingWin(networkIPAM)
}
}
@ -383,7 +383,7 @@ func (nIPAM *NetworkIPAM) Equal(equalable Equalable) bool {
}
}
func (nIPAM *NetworkIPAM) MergeFirstWin(networkIPAM *NetworkIPAM) {
func (nIPAM *NetworkIPAM) MergeExistingWin(networkIPAM *NetworkIPAM) {
switch {
case nIPAM == nil && networkIPAM == nil:
fallthrough
@ -399,7 +399,7 @@ func (nIPAM *NetworkIPAM) MergeFirstWin(networkIPAM *NetworkIPAM) {
// fallthrough
default:
nIPAM.mergeFirstWinConfig(networkIPAM.Configs)
nIPAM.mergeExistingWinConfig(networkIPAM.Configs)
}
}
@ -423,7 +423,7 @@ func (nIPAM *NetworkIPAM) MergeLastWin(networkIPAM *NetworkIPAM) {
}
}
func (nIPAM *NetworkIPAM) mergeFirstWinConfig(networkIPAMConfigs []*NetworkIPAMConfig) {
func (nIPAM *NetworkIPAM) mergeExistingWinConfig(networkIPAMConfigs []*NetworkIPAMConfig) {
for _, networkIPAMConfig := range networkIPAMConfigs {
if !existsInSlice(nIPAM.Configs, networkIPAMConfig) {
nIPAM.Configs = append(nIPAM.Configs, networkIPAMConfig)
@ -495,9 +495,9 @@ func (s *Secret) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin merges adds or overwrite the attributes of the passed secret
// MergeExistingWin merges adds or overwrite the attributes of the passed secret
// with the existing one.
func (s *Secret) MergeFirstWin(secret *Secret) {
func (s *Secret) MergeExistingWin(secret *Secret) {
if len(s.File) <= 0 {
s.File = secret.File
}
@ -518,6 +518,7 @@ func NewSecret() *Secret {
type Service struct {
CapabilitiesAdd []string `json:"cap_add,omitempty" yaml:"cap_add,omitempty"`
CapabilitiesDrop []string `json:"cap_drop,omitempty" yaml:"cap_drop,omitempty"`
DependsOn []string `json:"depends_on,omitempty" yaml:"depends_on,omitempty"`
Deploy *ServiceDeploy `json:"deploy,omitempty" yaml:"deploy,omitempty"`
Environments []string `json:"environment,omitempty" yaml:"environment,omitempty"`
ExtraHosts []string `json:"extra_hosts,omitempty" yaml:"extra_hosts,omitempty"`
@ -644,6 +645,7 @@ func (s *Service) Equal(equalable Equalable) bool {
default:
return equalSlice(s.CapabilitiesAdd, service.CapabilitiesAdd) &&
equalSlice(s.CapabilitiesDrop, service.CapabilitiesDrop) &&
equalSlice(s.DependsOn, service.DependsOn) &&
s.Deploy.Equal(service.Deploy) &&
equalSlice(s.Environments, service.Environments) &&
equalSlice(s.ExtraHosts, service.ExtraHosts) &&
@ -657,7 +659,7 @@ func (s *Service) Equal(equalable Equalable) bool {
}
}
func (s *Service) MergeFirstWin(service *Service) {
func (s *Service) MergeExistingWin(service *Service) {
switch {
case s == nil && service == nil:
fallthrough
@ -673,18 +675,19 @@ func (s *Service) MergeFirstWin(service *Service) {
// fallthrough
default:
s.mergeFirstWinCapabilitiesAdd(service.CapabilitiesAdd)
s.mergeFirstWinCapabilitiesDrop(service.CapabilitiesDrop)
s.mergeFirstWinDeploy(service.Deploy)
s.mergeFirstWinEnvironments(service.Environments)
s.mergeFirstWinExtraHosts(service.ExtraHosts)
s.mergeFirstWinImage(service.Image)
s.mergeFirstWinLabels(service.Labels)
s.mergeFirstWinNetworks(service.Networks)
s.mergeFirstWinPorts(service.Ports)
s.mergeFirstWinSecrets(service.Secrets)
s.mergeFirstWinULimits(service.ULimits)
s.mergeFirstWinVolumes(service.Volumes)
s.mergeExistingWinCapabilitiesAdd(service.CapabilitiesAdd)
s.mergeExistingWinCapabilitiesDrop(service.CapabilitiesDrop)
s.mergeExistingWinDependsOn(service.DependsOn)
s.mergeExistingWinDeploy(service.Deploy)
s.mergeExistingWinEnvironments(service.Environments)
s.mergeExistingWinExtraHosts(service.ExtraHosts)
s.mergeExistingWinImage(service.Image)
s.mergeExistingWinLabels(service.Labels)
s.mergeExistingWinNetworks(service.Networks)
s.mergeExistingWinPorts(service.Ports)
s.mergeExistingWinSecrets(service.Secrets)
s.mergeExistingWinULimits(service.ULimits)
s.mergeExistingWinVolumes(service.Volumes)
}
}
@ -708,6 +711,7 @@ func (s *Service) MergeLastWin(service *Service) {
default:
s.mergeLastWinCapabilitiesAdd(service.CapabilitiesAdd)
s.mergeLastWinCapabilitiesDrop(service.CapabilitiesDrop)
s.mergeLastWinDependsOn(service.DependsOn)
s.mergeLastWinDeploy(service.Deploy)
s.mergeLastWinEnvironments(service.Environments)
s.mergeLastWinExtraHosts(service.ExtraHosts)
@ -721,7 +725,7 @@ func (s *Service) MergeLastWin(service *Service) {
}
}
func (s *Service) mergeFirstWinCapabilitiesAdd(capabilitiesAdd []string) {
func (s *Service) mergeExistingWinCapabilitiesAdd(capabilitiesAdd []string) {
for _, capabilityAdd := range capabilitiesAdd {
if !existsInSlice(s.CapabilitiesAdd, capabilityAdd) && len(capabilityAdd) > 0 {
s.CapabilitiesAdd = append(s.CapabilitiesAdd, capabilityAdd)
@ -729,7 +733,7 @@ func (s *Service) mergeFirstWinCapabilitiesAdd(capabilitiesAdd []string) {
}
}
func (s *Service) mergeFirstWinCapabilitiesDrop(capabilitiesDrop []string) {
func (s *Service) mergeExistingWinCapabilitiesDrop(capabilitiesDrop []string) {
for _, capabilityDrop := range capabilitiesDrop {
if !existsInSlice(s.CapabilitiesAdd, capabilityDrop) && len(capabilityDrop) > 0 {
s.CapabilitiesDrop = append(s.CapabilitiesDrop, capabilityDrop)
@ -737,7 +741,15 @@ func (s *Service) mergeFirstWinCapabilitiesDrop(capabilitiesDrop []string) {
}
}
func (s *Service) mergeFirstWinDeploy(deploy *ServiceDeploy) {
func (s *Service) mergeExistingWinDependsOn(dependsOn []string) {
for _, depOn := range dependsOn {
if !existsInSlice(s.DependsOn, depOn) && len(depOn) > 0 {
s.DependsOn = append(s.DependsOn, depOn)
}
}
}
func (s *Service) mergeExistingWinDeploy(deploy *ServiceDeploy) {
switch {
case s.Deploy == nil && deploy != nil:
s.Deploy = deploy
@ -746,11 +758,11 @@ func (s *Service) mergeFirstWinDeploy(deploy *ServiceDeploy) {
case s.Deploy == nil && deploy == nil:
return
default:
s.Deploy.MergeFirstWin(deploy)
s.Deploy.MergeExistingWin(deploy)
}
}
func (s *Service) mergeFirstWinEnvironments(environments []string) {
func (s *Service) mergeExistingWinEnvironments(environments []string) {
switch {
case s.Environments == nil && environments != nil:
s.Environments = environments
@ -772,7 +784,7 @@ func (s *Service) mergeFirstWinEnvironments(environments []string) {
}
}
func (s *Service) mergeFirstWinImage(image string) {
func (s *Service) mergeExistingWinImage(image string) {
switch {
case len(s.Image) == 0 && len(image) != 0:
s.Image = image
@ -785,7 +797,7 @@ func (s *Service) mergeFirstWinImage(image string) {
}
}
func (s *Service) mergeFirstWinExtraHosts(extraHosts []string) {
func (s *Service) mergeExistingWinExtraHosts(extraHosts []string) {
for _, extraHost := range extraHosts {
if !existsInSlice(s.ExtraHosts, extraHost) && len(extraHost) > 0 {
s.ExtraHosts = append(s.ExtraHosts, extraHost)
@ -793,7 +805,7 @@ func (s *Service) mergeFirstWinExtraHosts(extraHosts []string) {
}
}
func (s *Service) mergeFirstWinLabels(labels []string) {
func (s *Service) mergeExistingWinLabels(labels []string) {
switch {
case s.Labels == nil && labels != nil:
s.Labels = labels
@ -815,7 +827,7 @@ func (s *Service) mergeFirstWinLabels(labels []string) {
}
}
func (s *Service) mergeFirstWinNetworks(networks map[string]*ServiceNetwork) {
func (s *Service) mergeExistingWinNetworks(networks map[string]*ServiceNetwork) {
switch {
case s.Networks == nil && networks != nil:
s.Networks = networks
@ -826,7 +838,7 @@ func (s *Service) mergeFirstWinNetworks(networks map[string]*ServiceNetwork) {
default:
for name, network := range networks {
if _, exists := s.Networks[name]; exists {
s.Networks[name].MergeFirstWin(network)
s.Networks[name].MergeExistingWin(network)
} else {
s.Networks[name] = network
}
@ -834,7 +846,7 @@ func (s *Service) mergeFirstWinNetworks(networks map[string]*ServiceNetwork) {
}
}
func (s *Service) mergeFirstWinPorts(ports []string) {
func (s *Service) mergeExistingWinPorts(ports []string) {
switch {
case s.Ports == nil && ports != nil:
s.Ports = ports
@ -844,6 +856,10 @@ func (s *Service) mergeFirstWinPorts(ports []string) {
return
default:
for _, port := range ports {
if len(port) <= 0 {
continue
}
src, dest, protocol := splitStringInPort(port)
if !s.ExistsDestinationPort(dest) {
s.SetPort(src, dest, protocol)
@ -852,7 +868,7 @@ func (s *Service) mergeFirstWinPorts(ports []string) {
}
}
func (s *Service) mergeFirstWinSecrets(secrets []string) {
func (s *Service) mergeExistingWinSecrets(secrets []string) {
for _, secret := range secrets {
if !existsInSlice(s.Secrets, secret) && len(secret) > 0 {
s.Secrets = append(s.Secrets, secret)
@ -860,7 +876,7 @@ func (s *Service) mergeFirstWinSecrets(secrets []string) {
}
}
func (s *Service) mergeFirstWinULimits(uLimits *ServiceULimits) {
func (s *Service) mergeExistingWinULimits(uLimits *ServiceULimits) {
switch {
case s.ULimits == nil && uLimits != nil:
s.ULimits = uLimits
@ -869,11 +885,11 @@ func (s *Service) mergeFirstWinULimits(uLimits *ServiceULimits) {
case s.ULimits == nil && uLimits == nil:
return
default:
s.ULimits.MergeFirstWin(uLimits)
s.ULimits.MergeExistingWin(uLimits)
}
}
func (s *Service) mergeFirstWinVolumes(volumes []string) {
func (s *Service) mergeExistingWinVolumes(volumes []string) {
switch {
case s.Volumes == nil && volumes != nil:
s.Volumes = volumes
@ -893,6 +909,10 @@ func (s *Service) mergeFirstWinVolumes(volumes []string) {
func (s *Service) mergeLastWinCapabilitiesAdd(capabilitiesAdd []string) {
for _, capabilityAdd := range capabilitiesAdd {
if len(capabilityAdd) <= 0 {
continue
}
if !existsInSlice(s.CapabilitiesAdd, capabilityAdd) {
s.CapabilitiesAdd = append(s.CapabilitiesAdd, capabilityAdd)
}
@ -901,12 +921,28 @@ func (s *Service) mergeLastWinCapabilitiesAdd(capabilitiesAdd []string) {
func (s *Service) mergeLastWinCapabilitiesDrop(capabilitiesDrop []string) {
for _, capabilityDrop := range capabilitiesDrop {
if !existsInSlice(s.CapabilitiesAdd, capabilityDrop) {
if len(capabilityDrop) <= 0 {
continue
}
if !existsInSlice(s.CapabilitiesDrop, capabilityDrop) {
s.CapabilitiesDrop = append(s.CapabilitiesDrop, capabilityDrop)
}
}
}
func (s *Service) mergeLastWinDependsOn(dependsOn []string) {
for _, dep := range dependsOn {
if len(dep) <= 0 {
continue
}
if !existsInSlice(s.DependsOn, dep) {
s.DependsOn = append(s.DependsOn, dep)
}
}
}
func (s *Service) mergeLastWinDeploy(deploy *ServiceDeploy) {
switch {
case s.Deploy == nil && deploy != nil:
@ -930,6 +966,10 @@ func (s *Service) mergeLastWinEnvironments(environments []string) {
return
default:
for _, environment := range environments {
if len(environment) <= 0 {
continue
}
key, value := splitStringInKeyValue(environment, environmentDelimiter)
s.SetEnvironment(key, value)
}
@ -953,6 +993,10 @@ func (s *Service) mergeLastWinImage(image string) {
func (s *Service) mergeLastWinExtraHosts(extraHosts []string) {
for _, extraHost := range extraHosts {
if len(extraHost) <= 0 {
continue
}
if !existsInSlice(s.ExtraHosts, extraHost) {
s.ExtraHosts = append(s.ExtraHosts, extraHost)
}
@ -969,6 +1013,10 @@ func (s *Service) mergeLastWinLabels(labels []string) {
return
default:
for _, label := range labels {
if len(label) <= 0 {
continue
}
key, value := splitStringInKeyValue(label, labelDelimiter)
s.SetLabel(key, value)
}
@ -1004,6 +1052,10 @@ func (s *Service) mergeLastWinPorts(ports []string) {
return
default:
for _, port := range ports {
if len(port) <= 0 {
continue
}
src, dest, protocol := splitStringInPort(port)
s.SetPort(src, dest, protocol)
}
@ -1012,6 +1064,10 @@ func (s *Service) mergeLastWinPorts(ports []string) {
func (s *Service) mergeLastWinSecrets(secrets []string) {
for _, secret := range secrets {
if len(secret) <= 0 {
continue
}
if !existsInSlice(s.Secrets, secret) {
s.Secrets = append(s.Secrets, secret)
}
@ -1041,6 +1097,10 @@ func (s *Service) mergeLastWinVolumes(volumes []string) {
return
default:
for _, volume := range volumes {
if len(volume) <= 0 {
continue
}
src, dest, perm := splitStringInVolume(volume)
s.SetVolume(src, dest, perm)
}
@ -1179,9 +1239,9 @@ func (sd *ServiceDeploy) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin merges adds or overwrite the attributes of the passed
// MergeExistingWin merges adds or overwrite the attributes of the passed
// serviceDeploy with the existing one.
func (sd *ServiceDeploy) MergeFirstWin(serviceDeploy *ServiceDeploy) {
func (sd *ServiceDeploy) MergeExistingWin(serviceDeploy *ServiceDeploy) {
switch {
case sd == nil && serviceDeploy == nil:
fallthrough
@ -1197,7 +1257,7 @@ func (sd *ServiceDeploy) MergeFirstWin(serviceDeploy *ServiceDeploy) {
// fallthrough
default:
sd.mergeFirstWinDeployResources(serviceDeploy.Resources)
sd.mergeExistingWinDeployResources(serviceDeploy.Resources)
}
}
@ -1223,7 +1283,7 @@ func (sd *ServiceDeploy) MergeLastWin(serviceDeploy *ServiceDeploy) {
}
}
func (sd *ServiceDeploy) mergeFirstWinDeployResources(resources *ServiceDeployResources) {
func (sd *ServiceDeploy) mergeExistingWinDeployResources(resources *ServiceDeployResources) {
switch {
case sd.Resources == nil && resources != nil:
sd.Resources = resources
@ -1232,7 +1292,7 @@ func (sd *ServiceDeploy) mergeFirstWinDeployResources(resources *ServiceDeployRe
case sd.Resources == nil && resources == nil:
return
default:
sd.Resources.MergeFirstWin(resources)
sd.Resources.MergeExistingWin(resources)
}
}
@ -1280,9 +1340,9 @@ func (sdr *ServiceDeployResources) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin adds only attributes of the passed serviceDeployResources if
// MergeExistingWin adds only attributes of the passed serviceDeployResources if
// they are not already exists.
func (sdr *ServiceDeployResources) MergeFirstWin(serviceDeployResources *ServiceDeployResources) {
func (sdr *ServiceDeployResources) MergeExistingWin(serviceDeployResources *ServiceDeployResources) {
switch {
case sdr == nil && serviceDeployResources == nil:
fallthrough
@ -1296,8 +1356,8 @@ func (sdr *ServiceDeployResources) MergeFirstWin(serviceDeployResources *Service
sdr = NewServiceDeployResources()
fallthrough
default:
sdr.mergeFirstWinLimits(serviceDeployResources.Limits)
sdr.mergeFirstWinReservations(serviceDeployResources.Reservations)
sdr.mergeExistingWinLimits(serviceDeployResources.Limits)
sdr.mergeExistingWinReservations(serviceDeployResources.Reservations)
}
}
@ -1322,7 +1382,7 @@ func (sdr *ServiceDeployResources) MergeLastWin(serviceDeployResources *ServiceD
}
}
func (sdr *ServiceDeployResources) mergeFirstWinLimits(limits *ServiceDeployResourcesLimits) {
func (sdr *ServiceDeployResources) mergeExistingWinLimits(limits *ServiceDeployResourcesLimits) {
switch {
case sdr.Limits == nil && limits != nil:
sdr.Limits = limits
@ -1331,11 +1391,11 @@ func (sdr *ServiceDeployResources) mergeFirstWinLimits(limits *ServiceDeployReso
case sdr.Limits == nil && limits == nil:
return
default:
sdr.Limits.MergeFirstWin(limits)
sdr.Limits.MergeExistingWin(limits)
}
}
func (sdr *ServiceDeployResources) mergeFirstWinReservations(reservations *ServiceDeployResourcesLimits) {
func (sdr *ServiceDeployResources) mergeExistingWinReservations(reservations *ServiceDeployResourcesLimits) {
switch {
case sdr.Reservations == nil && reservations != nil:
sdr.Reservations = reservations
@ -1344,7 +1404,7 @@ func (sdr *ServiceDeployResources) mergeFirstWinReservations(reservations *Servi
case sdr.Reservations == nil && reservations == nil:
return
default:
sdr.Reservations.MergeFirstWin(reservations)
sdr.Reservations.MergeExistingWin(reservations)
}
}
@ -1406,9 +1466,9 @@ func (sdrl *ServiceDeployResourcesLimits) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin adds only attributes of the passed serviceDeployResourcesLimits
// MergeExistingWin adds only attributes of the passed serviceDeployResourcesLimits
// if they are not already exists.
func (sdrl *ServiceDeployResourcesLimits) MergeFirstWin(serviceDeployResourcesLimits *ServiceDeployResourcesLimits) {
func (sdrl *ServiceDeployResourcesLimits) MergeExistingWin(serviceDeployResourcesLimits *ServiceDeployResourcesLimits) {
switch {
case sdrl == nil && serviceDeployResourcesLimits == nil:
fallthrough
@ -1424,8 +1484,8 @@ func (sdrl *ServiceDeployResourcesLimits) MergeFirstWin(serviceDeployResourcesLi
// fallthrough
default:
sdrl.mergeFirstWinCPUs(serviceDeployResourcesLimits.CPUs)
sdrl.mergeFirstWinMemory(serviceDeployResourcesLimits.Memory)
sdrl.mergeExistingWinCPUs(serviceDeployResourcesLimits.CPUs)
sdrl.mergeExistingWinMemory(serviceDeployResourcesLimits.Memory)
}
}
@ -1452,13 +1512,13 @@ func (sdrl *ServiceDeployResourcesLimits) MergeLastWin(serviceDeployResourcesLim
}
}
func (sdrl *ServiceDeployResourcesLimits) mergeFirstWinCPUs(cpus string) {
func (sdrl *ServiceDeployResourcesLimits) mergeExistingWinCPUs(cpus string) {
if len(sdrl.CPUs) <= 0 {
sdrl.CPUs = cpus
}
}
func (sdrl *ServiceDeployResourcesLimits) mergeFirstWinMemory(memory string) {
func (sdrl *ServiceDeployResourcesLimits) mergeExistingWinMemory(memory string) {
if len(sdrl.Memory) <= 0 {
sdrl.Memory = memory
}
@ -1503,9 +1563,9 @@ func (sn *ServiceNetwork) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin adds only attributes of the passed
// MergeExistingWin adds only attributes of the passed
// serviceNetwork if they are undefined.
func (sn *ServiceNetwork) MergeFirstWin(serviceNetwork *ServiceNetwork) {
func (sn *ServiceNetwork) MergeExistingWin(serviceNetwork *ServiceNetwork) {
switch {
case sn == nil && serviceNetwork == nil:
fallthrough
@ -1523,7 +1583,7 @@ func (sn *ServiceNetwork) MergeFirstWin(serviceNetwork *ServiceNetwork) {
sn = NewServiceNetwork()
fallthrough
default:
sn.mergeFirstWinAliases(serviceNetwork.Aliases)
sn.mergeExistingWinAliases(serviceNetwork.Aliases)
}
}
@ -1551,7 +1611,7 @@ func (sn *ServiceNetwork) MergeLastWin(serviceNetwork *ServiceNetwork) {
}
}
func (sn *ServiceNetwork) mergeFirstWinAliases(aliases []string) {
func (sn *ServiceNetwork) mergeExistingWinAliases(aliases []string) {
for _, alias := range aliases {
if !existsInSlice(sn.Aliases, alias) && len(alias) > 0 {
sn.Aliases = append(sn.Aliases, alias)
@ -1598,9 +1658,9 @@ func (l *ServiceULimits) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin adds only the attributes of the passed ServiceULimits they are
// MergeExistingWin adds only the attributes of the passed ServiceULimits they are
// undefined.
func (l *ServiceULimits) MergeFirstWin(serviceULimits *ServiceULimits) {
func (l *ServiceULimits) MergeExistingWin(serviceULimits *ServiceULimits) {
switch {
case l == nil && serviceULimits == nil:
fallthrough
@ -1615,8 +1675,8 @@ func (l *ServiceULimits) MergeFirstWin(serviceULimits *ServiceULimits) {
// fallthrough
default:
l.mergeFirstWinNProc(serviceULimits.NProc)
l.mergeFirstWinNoFile(serviceULimits.NoFile)
l.mergeExistingWinNProc(serviceULimits.NProc)
l.mergeExistingWinNoFile(serviceULimits.NoFile)
}
}
@ -1642,16 +1702,16 @@ func (l *ServiceULimits) MergeLastWin(serviceULimits *ServiceULimits) {
}
}
func (l *ServiceULimits) mergeFirstWinNProc(nproc uint) {
func (l *ServiceULimits) mergeExistingWinNProc(nproc uint) {
if l.NProc != nproc {
return
}
l.NProc = nproc
}
func (l *ServiceULimits) mergeFirstWinNoFile(noFile *ServiceULimitsNoFile) {
func (l *ServiceULimits) mergeExistingWinNoFile(noFile *ServiceULimitsNoFile) {
if !l.NoFile.Equal(noFile) {
l.NoFile.MergeFirstWin(noFile)
l.NoFile.MergeExistingWin(noFile)
}
}
@ -1698,9 +1758,9 @@ func (nf *ServiceULimitsNoFile) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin adds only the attributes of the passed ServiceULimits they are
// MergeExistingWin adds only the attributes of the passed ServiceULimits they are
// undefined.
func (nf *ServiceULimitsNoFile) MergeFirstWin(serviceULimitsNoFile *ServiceULimitsNoFile) {
func (nf *ServiceULimitsNoFile) MergeExistingWin(serviceULimitsNoFile *ServiceULimitsNoFile) {
switch {
case nf == nil && serviceULimitsNoFile == nil:
fallthrough
@ -1716,8 +1776,8 @@ func (nf *ServiceULimitsNoFile) MergeFirstWin(serviceULimitsNoFile *ServiceULimi
// fallthrough
default:
nf.mergeFirstWinHard(serviceULimitsNoFile.Hard)
nf.mergeFirstWinSoft(serviceULimitsNoFile.Soft)
nf.mergeExistingWinHard(serviceULimitsNoFile.Hard)
nf.mergeExistingWinSoft(serviceULimitsNoFile.Soft)
}
}
@ -1744,14 +1804,14 @@ func (nf *ServiceULimitsNoFile) MergeLastWin(serviceULimitsNoFile *ServiceULimit
}
}
func (nf *ServiceULimitsNoFile) mergeFirstWinHard(hard uint) {
func (nf *ServiceULimitsNoFile) mergeExistingWinHard(hard uint) {
if nf.Hard != hard {
return
}
nf.Hard = hard
}
func (nf *ServiceULimitsNoFile) mergeFirstWinSoft(soft uint) {
func (nf *ServiceULimitsNoFile) mergeExistingWinSoft(soft uint) {
if nf.Soft != soft {
return
}
@ -1797,9 +1857,9 @@ func (v *Volume) Equal(equalable Equalable) bool {
}
}
// MergeFirstWin adds only the attributes of the passed Volume they are
// MergeExistingWin adds only the attributes of the passed Volume they are
// undefined.
func (v *Volume) MergeFirstWin(volume *Volume) {
func (v *Volume) MergeExistingWin(volume *Volume) {
switch {
case v == nil && volume == nil:
fallthrough
@ -1814,7 +1874,7 @@ func (v *Volume) MergeFirstWin(volume *Volume) {
// fallthrough
default:
v.mergeFirstWinExternal(volume.External)
v.mergeExistingWinExternal(volume.External)
}
}
@ -1837,7 +1897,7 @@ func (v *Volume) MergeLastWin(volume *Volume) {
}
}
func (v *Volume) mergeFirstWinExternal(external bool) {
func (v *Volume) mergeExistingWinExternal(external bool) {
if v.External {
return
}

View File

@ -225,6 +225,7 @@ func TestService_Equal(t *testing.T) {
equalableA: &dockerCompose.Service{
CapabilitiesAdd: []string{},
CapabilitiesDrop: []string{},
DependsOn: []string{},
Deploy: nil,
Environments: []string{},
ExtraHosts: []string{},
@ -239,6 +240,7 @@ func TestService_Equal(t *testing.T) {
equalableB: &dockerCompose.Service{
CapabilitiesAdd: []string{},
CapabilitiesDrop: []string{},
DependsOn: []string{},
Deploy: nil,
Environments: []string{},
ExtraHosts: []string{},
@ -288,6 +290,24 @@ func TestService_Equal(t *testing.T) {
},
expectedResult: false,
},
{
equalableA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
equalableB: &dockerCompose.Service{
DependsOn: []string{},
},
expectedResult: false,
},
{
equalableA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
equalableB: &dockerCompose.Service{
DependsOn: []string{"app"},
},
expectedResult: true,
},
{
equalableA: &dockerCompose.Service{
Deploy: &dockerCompose.ServiceDeploy{},
@ -464,7 +484,7 @@ func TestService_Equal(t *testing.T) {
}
}
func TestService_MergeFirstWin(t *testing.T) {
func TestService_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -575,6 +595,52 @@ func TestService_MergeFirstWin(t *testing.T) {
},
},
// DependsOn
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{"app"},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{"app"},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{""},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
// Deploy
{
serviceDeploymentA: &dockerCompose.Service{
@ -1360,7 +1426,7 @@ func TestService_MergeFirstWin(t *testing.T) {
}
for i, testCase := range testCases {
testCase.serviceDeploymentA.MergeFirstWin(testCase.serviceDeploymentB)
testCase.serviceDeploymentA.MergeExistingWin(testCase.serviceDeploymentB)
require.True(testCase.expectedService.Equal(testCase.serviceDeploymentA), "Failed test case %v", i)
}
}
@ -1418,6 +1484,17 @@ func TestService_MergeLastWin(t *testing.T) {
CapabilitiesAdd: []string{"NET_RAW"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
CapabilitiesAdd: []string{"NET_RAW"},
},
serviceDeploymentB: &dockerCompose.Service{
CapabilitiesAdd: []string{""},
},
expectedService: &dockerCompose.Service{
CapabilitiesAdd: []string{"NET_RAW"},
},
},
// CapabilitiesDrop
{
@ -1453,6 +1530,63 @@ func TestService_MergeLastWin(t *testing.T) {
CapabilitiesDrop: []string{"NET_RAW"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
CapabilitiesDrop: []string{"NET_RAW"},
},
serviceDeploymentB: &dockerCompose.Service{
CapabilitiesDrop: []string{""},
},
expectedService: &dockerCompose.Service{
CapabilitiesDrop: []string{"NET_RAW"},
},
},
// DependsOn
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{"app"},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{"app"},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
DependsOn: []string{"app"},
},
serviceDeploymentB: &dockerCompose.Service{
DependsOn: []string{""},
},
expectedService: &dockerCompose.Service{
DependsOn: []string{"app"},
},
},
// Deploy
{
@ -1567,6 +1701,17 @@ func TestService_MergeLastWin(t *testing.T) {
Environments: []string{"PROXY_HOST=u.example.local"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Environments: []string{"PROXY_HOST=u.example.com"},
},
serviceDeploymentB: &dockerCompose.Service{
Environments: []string{""},
},
expectedService: &dockerCompose.Service{
Environments: []string{"PROXY_HOST=u.example.com"},
},
},
// ExtraHosts
{
@ -1635,6 +1780,17 @@ func TestService_MergeLastWin(t *testing.T) {
ExtraHosts: []string{"extra.host.com", "extra.host.local"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
ExtraHosts: []string{"extra.host.local"},
},
serviceDeploymentB: &dockerCompose.Service{
ExtraHosts: []string{""},
},
expectedService: &dockerCompose.Service{
ExtraHosts: []string{"extra.host.local"},
},
},
// Image
{
@ -1738,6 +1894,17 @@ func TestService_MergeLastWin(t *testing.T) {
Labels: []string{"prometheus.io/scrape=true"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Labels: []string{"prometheus.io/scrape=true"},
},
serviceDeploymentB: &dockerCompose.Service{
Labels: []string{""},
},
expectedService: &dockerCompose.Service{
Labels: []string{"prometheus.io/scrape=true"},
},
},
// Networks
{
@ -1817,6 +1984,23 @@ func TestService_MergeLastWin(t *testing.T) {
},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Networks: map[string]*dockerCompose.ServiceNetwork{
"proxy": {Aliases: []string{"app.proxy.network"}},
},
},
serviceDeploymentB: &dockerCompose.Service{
Networks: map[string]*dockerCompose.ServiceNetwork{
"proxy": {Aliases: []string{""}},
},
},
expectedService: &dockerCompose.Service{
Networks: map[string]*dockerCompose.ServiceNetwork{
"proxy": {Aliases: []string{"app.proxy.network"}},
},
},
},
// Ports
{
@ -1907,6 +2091,17 @@ func TestService_MergeLastWin(t *testing.T) {
Ports: []string{"10080:80/udp"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Ports: []string{"80:80"},
},
serviceDeploymentB: &dockerCompose.Service{
Ports: []string{""},
},
expectedService: &dockerCompose.Service{
Ports: []string{"80:80"},
},
},
// Secrets
{
@ -1975,6 +2170,17 @@ func TestService_MergeLastWin(t *testing.T) {
Secrets: []string{"db_pass_credentials", "oauth2_pass_credentials"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Secrets: []string{"db_pass_credentials"},
},
serviceDeploymentB: &dockerCompose.Service{
Secrets: []string{""},
},
expectedService: &dockerCompose.Service{
Secrets: []string{"db_pass_credentials"},
},
},
// ULimits
{
@ -2147,6 +2353,17 @@ func TestService_MergeLastWin(t *testing.T) {
Volumes: []string{"/usr/share/zoneinfo/Europe/Berlin:/etc/localtime"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Volumes: []string{"/etc/localtime:/etc/localtime"},
},
serviceDeploymentB: &dockerCompose.Service{
Volumes: []string{""},
},
expectedService: &dockerCompose.Service{
Volumes: []string{"/etc/localtime:/etc/localtime"},
},
},
}
for i, testCase := range testCases {
@ -2196,7 +2413,7 @@ func TestSecretDeploy_Equal(t *testing.T) {
}
}
func TestServiceDeploy_MergeFirstWin(t *testing.T) {
func TestServiceDeploy_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -2377,7 +2594,7 @@ func TestSecretDeployResources_Equal(t *testing.T) {
}
}
func TestServiceDeployResources_MergeFirstWin(t *testing.T) {
func TestServiceDeployResources_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -2521,7 +2738,7 @@ func TestServiceDeployResources_MergeFirstWin(t *testing.T) {
}
for i, testCase := range testCases {
testCase.serviceDeploymentResourcesA.MergeFirstWin(testCase.serviceDeploymentResourcesB)
testCase.serviceDeploymentResourcesA.MergeExistingWin(testCase.serviceDeploymentResourcesB)
require.True(testCase.expectedServiceDeploymentResources.Equal(testCase.serviceDeploymentResourcesA), "Failed test case %v", i)
}
}
@ -2715,7 +2932,7 @@ func TestServiceDeployResourcesLimits_Equal(t *testing.T) {
}
}
func TestServiceDeployResourcesLimits_MergeFirstWin(t *testing.T) {
func TestServiceDeployResourcesLimits_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -2803,7 +3020,7 @@ func TestServiceDeployResourcesLimits_MergeFirstWin(t *testing.T) {
}
for i, testCase := range testCases {
testCase.serviceDeploymentResourcesLimitsA.MergeFirstWin(testCase.serviceDeploymentResourcesLimitsB)
testCase.serviceDeploymentResourcesLimitsA.MergeExistingWin(testCase.serviceDeploymentResourcesLimitsB)
require.True(testCase.expectedServiceDeploymentResourcesLimits.Equal(testCase.serviceDeploymentResourcesLimitsA), "Failed test case %v", i)
}
}
@ -2941,7 +3158,7 @@ func TestServiceNetwork_Equal(t *testing.T) {
}
}
func TestServiceNetwork_MergeFirstWin(t *testing.T) {
func TestServiceNetwork_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -2995,7 +3212,7 @@ func TestServiceNetwork_MergeFirstWin(t *testing.T) {
}
for i, testCase := range testCases {
testCase.ServiceNetworkA.MergeFirstWin(testCase.ServiceNetworkB)
testCase.ServiceNetworkA.MergeExistingWin(testCase.ServiceNetworkB)
require.True(testCase.expectedServiceNetwork.Equal(testCase.ServiceNetworkA), "Failed test case %v", i)
}
}
@ -3163,7 +3380,7 @@ func TestServiceULimits_MergeLastWin(t *testing.T) {
}
}
func TestServiceULimits_MergeFirstWin(t *testing.T) {
func TestServiceULimits_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -3206,7 +3423,7 @@ func TestServiceULimits_MergeFirstWin(t *testing.T) {
}
for i, testCase := range testCases {
testCase.ServiceULimitsA.MergeFirstWin(testCase.ServiceULimitsB)
testCase.ServiceULimitsA.MergeExistingWin(testCase.ServiceULimitsB)
require.True(testCase.expectedServiceULimits.Equal(testCase.ServiceULimitsA), "Failed test case %v", i)
}
}
@ -3261,7 +3478,7 @@ func TestServiceULimitsNoFile_Equal(t *testing.T) {
}
}
func TestServiceULimitsNoFile_MergeFirstWin(t *testing.T) {
func TestServiceULimitsNoFile_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -3338,7 +3555,7 @@ func TestServiceULimitsNoFile_MergeFirstWin(t *testing.T) {
}
for i, testCase := range testCases {
testCase.ServiceULimitsNoFileA.MergeFirstWin(testCase.ServiceULimitsNoFileB)
testCase.ServiceULimitsNoFileA.MergeExistingWin(testCase.ServiceULimitsNoFileB)
require.True(testCase.expectedServiceULimitsNoFile.Equal(testCase.ServiceULimitsNoFileA), "Failed test case %v", i)
}
}
@ -3473,7 +3690,7 @@ func TestVolume_Equal(t *testing.T) {
}
}
func TestVolume_MergeFirstWin(t *testing.T) {
func TestVolume_MergeExistingWin(t *testing.T) {
require := require.New(t)
testCases := []struct {
@ -3527,7 +3744,7 @@ func TestVolume_MergeFirstWin(t *testing.T) {
}
for i, testCase := range testCases {
testCase.volumeA.MergeFirstWin(testCase.volumeB)
testCase.volumeA.MergeExistingWin(testCase.volumeB)
require.True(testCase.expectedVolume.Equal(testCase.volumeA), "Failed test case %v", i)
}
}

View File

@ -1,6 +1,8 @@
version: "3.3"
services:
app:
depends_on:
- oracle
environment:
- HTTP_PROXY=1.2.3.4:8080
image: repository:version

View File

@ -1,6 +1,8 @@
version: "3.3"
services:
app:
depends_on:
- postgres
environment:
- HTTP_PROXY=4.3.2.1:8080
image: repository:version