Skip to content

Commit

Permalink
Merge pull request #95 from adevinta/merge-configurations
Browse files Browse the repository at this point in the history
internal/config: add merging configuration functionality
  • Loading branch information
seilagamo authored Sep 19, 2024
2 parents c75747c + b3d4900 commit c6c042c
Show file tree
Hide file tree
Showing 4 changed files with 314 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/adevinta/lava
go 1.21.1

require (
dario.cat/mergo v1.0.1
github.com/adevinta/vulcan-agent v1.2.17
github.com/adevinta/vulcan-check-catalog v0.0.0-20240321120804-fe4ed05f8505
github.com/adevinta/vulcan-report v1.0.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
Expand Down
29 changes: 29 additions & 0 deletions internal/config/merge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2024 Adevinta

package config

import (
"fmt"

"dario.cat/mergo"
)

// merge merges two configurations. The values of the configuration
// passed as first parameter will be overridden by those in the
// configuration passed as second parameter avoiding overriding with
// nil values.
func merge(dst, src Config) (Config, error) {
merged := Config{}
mergeOpts := []func(*mergo.Config){
mergo.WithOverride,
mergo.WithoutDereference,
mergo.WithAppendSlice,
}
if err := mergo.Merge(&merged, dst, mergeOpts...); err != nil {
return Config{}, fmt.Errorf("merging dst config into new config: %w", err)
}
if err := mergo.Merge(&merged, src, mergeOpts...); err != nil {
return Config{}, fmt.Errorf("merging src config into new config: %w", err)
}
return merged, nil
}
282 changes: 282 additions & 0 deletions internal/config/merge_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
// Copyright 2024 Adevinta

package config

import (
"testing"

agentconfig "github.com/adevinta/vulcan-agent/config"
"github.com/google/go-cmp/cmp"
)

func TestLavaMerger_Merge(t *testing.T) {
tests := []struct {
name string
dst Config
src Config
want Config
wantErr bool
}{
{
name: "Two empty configurations",
dst: Config{},
src: Config{},
want: Config{},
wantErr: false,
},
{
name: "Simple case",
dst: Config{},
src: Config{
LavaVersion: ptr("v1.0.0"),
},
want: Config{
LavaVersion: ptr("v1.0.0"),
},
wantErr: false,
},
{
name: "Settings with default values won't override",
dst: Config{
LavaVersion: ptr("v1.0.0"),
AgentConfig: AgentConfig{
PullPolicy: ptr(agentconfig.PullPolicyAlways),
Parallel: ptr(4),
Vars: map[string]string{
"VAR1": "value1",
"VAR2": "value2",
},
RegistryAuths: []RegistryAuth{
{
Server: "server",
Username: "username",
Password: "password",
},
},
},
ReportConfig: ReportConfig{
Severity: ptr(SeverityCritical),
ShowSeverity: ptr(SeverityLow),
Format: ptr(OutputFormatJSON),
OutputFile: ptr("outputfile.json"),
ErrorOnStaleExclusions: ptr(true),
Exclusions: []Exclusion{
{Summary: "Summary 1"},
},
Metrics: ptr("metrics.json"),
},
},
src: Config{},
want: Config{
LavaVersion: ptr("v1.0.0"),
AgentConfig: AgentConfig{
PullPolicy: ptr(agentconfig.PullPolicyAlways),
Parallel: ptr(4),
Vars: map[string]string{
"VAR1": "value1",
"VAR2": "value2",
},
RegistryAuths: []RegistryAuth{
{
Server: "server",
Username: "username",
Password: "password",
},
},
},
ReportConfig: ReportConfig{
Severity: ptr(SeverityCritical),
ShowSeverity: ptr(SeverityLow),
Format: ptr(OutputFormatJSON),
OutputFile: ptr("outputfile.json"),
ErrorOnStaleExclusions: ptr(true),
Exclusions: []Exclusion{
{
Summary: "Summary 1",
},
},
Metrics: ptr("metrics.json"),
},
},
wantErr: false,
},
{
name: "Override value",
dst: Config{
LavaVersion: ptr("v1.0.0"),
AgentConfig: AgentConfig{
PullPolicy: ptr(agentconfig.PullPolicyAlways),
Parallel: ptr(4),
Vars: map[string]string{
"VAR3": "value3",
"VAR4": "value4",
},
RegistryAuths: []RegistryAuth{
{
Server: "server2",
Username: "username2",
Password: "password2",
},
},
},
ReportConfig: ReportConfig{
Severity: ptr(SeverityCritical),
ShowSeverity: ptr(SeverityLow),
Format: ptr(OutputFormatJSON),
OutputFile: ptr("outputfile2.json"),
ErrorOnStaleExclusions: ptr(true),
Exclusions: []Exclusion{
{
Summary: "Summary 2",
},
},
Metrics: ptr("metrics2.json"),
},
},
src: Config{
LavaVersion: ptr("v1.0.1"),
AgentConfig: AgentConfig{
PullPolicy: ptr(agentconfig.PullPolicyNever),
Parallel: ptr(3),
Vars: map[string]string{
"VAR1": "value1",
"VAR2": "value2",
},
RegistryAuths: []RegistryAuth{
{
Server: "server",
Username: "username",
Password: "password",
},
},
},
ReportConfig: ReportConfig{
Severity: ptr(SeverityCritical),
ShowSeverity: ptr(SeverityLow),
Format: ptr(OutputFormatJSON),
OutputFile: ptr("outputfile1.json"),
ErrorOnStaleExclusions: ptr(false),
Exclusions: []Exclusion{
{
Summary: "Summary 1",
},
},
Metrics: ptr("metrics2.json"),
},
},
want: Config{
LavaVersion: ptr("v1.0.1"),
AgentConfig: AgentConfig{
PullPolicy: ptr(agentconfig.PullPolicyNever),
Parallel: ptr(3),
Vars: map[string]string{
"VAR1": "value1",
"VAR2": "value2",
"VAR3": "value3",
"VAR4": "value4",
},
RegistryAuths: []RegistryAuth{
{
Server: "server2",
Username: "username2",
Password: "password2",
},
{
Server: "server",
Username: "username",
Password: "password",
},
},
},
ReportConfig: ReportConfig{
Severity: ptr(SeverityCritical),
ShowSeverity: ptr(SeverityLow),
Format: ptr(OutputFormatJSON),
OutputFile: ptr("outputfile1.json"),
ErrorOnStaleExclusions: ptr(false),
Exclusions: []Exclusion{
{Summary: "Summary 2"},
{Summary: "Summary 1"},
},
Metrics: ptr("metrics2.json"),
},
},
wantErr: false,
},
{
name: "Append Exclusions",
dst: Config{
ReportConfig: ReportConfig{
Exclusions: []Exclusion{
{
Summary: "Summary 2",
},
},
},
},
src: Config{
ReportConfig: ReportConfig{
Exclusions: []Exclusion{
{
Summary: "Summary 1",
},
},
},
},
want: Config{
ReportConfig: ReportConfig{
Exclusions: []Exclusion{
{
Summary: "Summary 2",
},
{
Summary: "Summary 1",
},
},
},
},
wantErr: false,
},
{
name: "Duplicated Exclusions",
dst: Config{
ReportConfig: ReportConfig{
Exclusions: []Exclusion{
{
Summary: "Summary 1",
},
},
},
},
src: Config{
ReportConfig: ReportConfig{
Exclusions: []Exclusion{
{
Summary: "Summary 1",
},
},
},
},
want: Config{
ReportConfig: ReportConfig{
Exclusions: []Exclusion{
{Summary: "Summary 1"},
{Summary: "Summary 1"},
},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := merge(tt.dst, tt.src)
if (err != nil) != tt.wantErr {
t.Errorf("unexpected error value: %v", err)
}
if diff := cmp.Diff(tt.want, got); diff != "" {
t.Errorf("configs mismatch (-want +got):\n%v", diff)
}
})
}
}

0 comments on commit c6c042c

Please sign in to comment.