Compare commits
4 Commits
669ebd0f25
...
b83efda648
Author | SHA1 | Date | |
---|---|---|---|
b83efda648 | |||
5dea30fec0 | |||
3d97ee0ab8 | |||
8b68c9587c |
@ -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
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"rewrap.wrappingColumn": 120,
|
||||
}
|
33
README.md
33
README.md
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
@ -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) &&
|
||||
@ -675,6 +677,7 @@ func (s *Service) MergeExistingWin(service *Service) {
|
||||
default:
|
||||
s.mergeExistingWinCapabilitiesAdd(service.CapabilitiesAdd)
|
||||
s.mergeExistingWinCapabilitiesDrop(service.CapabilitiesDrop)
|
||||
s.mergeExistingWinDependsOn(service.DependsOn)
|
||||
s.mergeExistingWinDeploy(service.Deploy)
|
||||
s.mergeExistingWinEnvironments(service.Environments)
|
||||
s.mergeExistingWinExtraHosts(service.ExtraHosts)
|
||||
@ -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)
|
||||
@ -737,6 +741,14 @@ func (s *Service) mergeExistingWinCapabilitiesDrop(capabilitiesDrop []string) {
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
@ -913,12 +925,24 @@ func (s *Service) mergeLastWinCapabilitiesDrop(capabilitiesDrop []string) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !existsInSlice(s.CapabilitiesAdd, capabilityDrop) {
|
||||
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:
|
||||
|
@ -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{},
|
||||
@ -575,6 +595,52 @@ func TestService_MergeExistingWin(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{
|
||||
@ -1476,6 +1542,52 @@ func TestService_MergeLastWin(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{
|
||||
|
@ -1,6 +1,8 @@
|
||||
version: "3.3"
|
||||
services:
|
||||
app:
|
||||
depends_on:
|
||||
- oracle
|
||||
environment:
|
||||
- HTTP_PROXY=1.2.3.4:8080
|
||||
image: repository:version
|
||||
|
@ -1,6 +1,8 @@
|
||||
version: "3.3"
|
||||
services:
|
||||
app:
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
- HTTP_PROXY=4.3.2.1:8080
|
||||
image: repository:version
|
||||
|
Loading…
Reference in New Issue
Block a user