Compare commits

..

No commits in common. "b83efda64829526e11abd4efdcb5ab32945475b0" and "669ebd0f25ff9cfb4ebb7e4a7e822a66093291fa" have entirely different histories.

7 changed files with 28 additions and 164 deletions

View File

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

View File

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

View File

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

View File

@ -66,25 +66,25 @@ func (c *Config) ExistsVolume(name string) bool {
// Merge adds only a missing network, secret, service and volume. // Merge adds only a missing network, secret, service and volume.
func (c *Config) Merge(config *Config) { func (c *Config) Merge(config *Config) {
for name, network := range config.Networks { for name, network := range c.Networks {
if !c.ExistsNetwork(name) { if !c.ExistsNetwork(name) {
c.Networks[name] = network c.Networks[name] = network
} }
} }
for name, secret := range config.Secrets { for name, secret := range c.Secrets {
if !c.ExistsSecret(name) { if !c.ExistsSecret(name) {
c.Secrets[name] = secret c.Secrets[name] = secret
} }
} }
for name, service := range config.Services { for name, service := range c.Services {
if !c.ExistsService(name) { if !c.ExistsService(name) {
c.Services[name] = service c.Services[name] = service
} }
} }
for name, volume := range config.Volumes { for name, volume := range c.Volumes {
if !c.ExistsVolume(name) { if !c.ExistsVolume(name) {
c.Volumes[name] = volume c.Volumes[name] = volume
} }
@ -518,7 +518,6 @@ func NewSecret() *Secret {
type Service struct { type Service struct {
CapabilitiesAdd []string `json:"cap_add,omitempty" yaml:"cap_add,omitempty"` CapabilitiesAdd []string `json:"cap_add,omitempty" yaml:"cap_add,omitempty"`
CapabilitiesDrop []string `json:"cap_drop,omitempty" yaml:"cap_drop,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"` Deploy *ServiceDeploy `json:"deploy,omitempty" yaml:"deploy,omitempty"`
Environments []string `json:"environment,omitempty" yaml:"environment,omitempty"` Environments []string `json:"environment,omitempty" yaml:"environment,omitempty"`
ExtraHosts []string `json:"extra_hosts,omitempty" yaml:"extra_hosts,omitempty"` ExtraHosts []string `json:"extra_hosts,omitempty" yaml:"extra_hosts,omitempty"`
@ -645,7 +644,6 @@ func (s *Service) Equal(equalable Equalable) bool {
default: default:
return equalSlice(s.CapabilitiesAdd, service.CapabilitiesAdd) && return equalSlice(s.CapabilitiesAdd, service.CapabilitiesAdd) &&
equalSlice(s.CapabilitiesDrop, service.CapabilitiesDrop) && equalSlice(s.CapabilitiesDrop, service.CapabilitiesDrop) &&
equalSlice(s.DependsOn, service.DependsOn) &&
s.Deploy.Equal(service.Deploy) && s.Deploy.Equal(service.Deploy) &&
equalSlice(s.Environments, service.Environments) && equalSlice(s.Environments, service.Environments) &&
equalSlice(s.ExtraHosts, service.ExtraHosts) && equalSlice(s.ExtraHosts, service.ExtraHosts) &&
@ -677,7 +675,6 @@ func (s *Service) MergeExistingWin(service *Service) {
default: default:
s.mergeExistingWinCapabilitiesAdd(service.CapabilitiesAdd) s.mergeExistingWinCapabilitiesAdd(service.CapabilitiesAdd)
s.mergeExistingWinCapabilitiesDrop(service.CapabilitiesDrop) s.mergeExistingWinCapabilitiesDrop(service.CapabilitiesDrop)
s.mergeExistingWinDependsOn(service.DependsOn)
s.mergeExistingWinDeploy(service.Deploy) s.mergeExistingWinDeploy(service.Deploy)
s.mergeExistingWinEnvironments(service.Environments) s.mergeExistingWinEnvironments(service.Environments)
s.mergeExistingWinExtraHosts(service.ExtraHosts) s.mergeExistingWinExtraHosts(service.ExtraHosts)
@ -711,7 +708,6 @@ func (s *Service) MergeLastWin(service *Service) {
default: default:
s.mergeLastWinCapabilitiesAdd(service.CapabilitiesAdd) s.mergeLastWinCapabilitiesAdd(service.CapabilitiesAdd)
s.mergeLastWinCapabilitiesDrop(service.CapabilitiesDrop) s.mergeLastWinCapabilitiesDrop(service.CapabilitiesDrop)
s.mergeLastWinDependsOn(service.DependsOn)
s.mergeLastWinDeploy(service.Deploy) s.mergeLastWinDeploy(service.Deploy)
s.mergeLastWinEnvironments(service.Environments) s.mergeLastWinEnvironments(service.Environments)
s.mergeLastWinExtraHosts(service.ExtraHosts) s.mergeLastWinExtraHosts(service.ExtraHosts)
@ -741,14 +737,6 @@ 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) { func (s *Service) mergeExistingWinDeploy(deploy *ServiceDeploy) {
switch { switch {
case s.Deploy == nil && deploy != nil: case s.Deploy == nil && deploy != nil:
@ -925,24 +913,12 @@ func (s *Service) mergeLastWinCapabilitiesDrop(capabilitiesDrop []string) {
continue continue
} }
if !existsInSlice(s.CapabilitiesDrop, capabilityDrop) { if !existsInSlice(s.CapabilitiesAdd, capabilityDrop) {
s.CapabilitiesDrop = append(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) { func (s *Service) mergeLastWinDeploy(deploy *ServiceDeploy) {
switch { switch {
case s.Deploy == nil && deploy != nil: case s.Deploy == nil && deploy != nil:

View File

@ -225,7 +225,6 @@ func TestService_Equal(t *testing.T) {
equalableA: &dockerCompose.Service{ equalableA: &dockerCompose.Service{
CapabilitiesAdd: []string{}, CapabilitiesAdd: []string{},
CapabilitiesDrop: []string{}, CapabilitiesDrop: []string{},
DependsOn: []string{},
Deploy: nil, Deploy: nil,
Environments: []string{}, Environments: []string{},
ExtraHosts: []string{}, ExtraHosts: []string{},
@ -240,7 +239,6 @@ func TestService_Equal(t *testing.T) {
equalableB: &dockerCompose.Service{ equalableB: &dockerCompose.Service{
CapabilitiesAdd: []string{}, CapabilitiesAdd: []string{},
CapabilitiesDrop: []string{}, CapabilitiesDrop: []string{},
DependsOn: []string{},
Deploy: nil, Deploy: nil,
Environments: []string{}, Environments: []string{},
ExtraHosts: []string{}, ExtraHosts: []string{},
@ -290,24 +288,6 @@ func TestService_Equal(t *testing.T) {
}, },
expectedResult: false, 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{ equalableA: &dockerCompose.Service{
Deploy: &dockerCompose.ServiceDeploy{}, Deploy: &dockerCompose.ServiceDeploy{},
@ -595,52 +575,6 @@ 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 // Deploy
{ {
serviceDeploymentA: &dockerCompose.Service{ serviceDeploymentA: &dockerCompose.Service{
@ -1542,52 +1476,6 @@ 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 // Deploy
{ {
serviceDeploymentA: &dockerCompose.Service{ serviceDeploymentA: &dockerCompose.Service{

View File

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

View File

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