Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a NoDeletes function to the Syncer #143

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions pkg/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ type Syncer struct {
// enableEntityActions enables entity actions and disables direct output prints. If set to true, clients must
// consume the Syncer.resultChan channel or Syncer.Solve() will block.
enableEntityActions bool

// Prevents the Syncer from performing any Delete operations. Default is false (will delete).
noDeletes bool
}

type SyncerOpts struct {
Expand All @@ -173,6 +176,9 @@ type SyncerOpts struct {
// EnableEntityActions instructs the Syncer to send EntityActions to its resultChan. If enabled, clients must
// consume the Syncer.resultChan channel or Syncer.Solve() will block.
EnableEntityActions bool

// Prevents the Syncer from performing any Delete operations. Default is false (will delete).
NoDeletes bool
}

// NewSyncer constructs a Syncer.
Expand All @@ -196,6 +202,7 @@ func NewSyncer(opts SyncerOpts) (*Syncer, error) {
isKonnect: opts.IsKonnect,

enableEntityActions: opts.EnableEntityActions,
noDeletes: opts.NoDeletes,
}

if opts.IsKonnect {
Expand Down Expand Up @@ -278,11 +285,20 @@ func (sc *Syncer) init() error {
}

func (sc *Syncer) diff() error {
for _, operation := range []func() error{
sc.deleteDuplicates,
sc.createUpdate,
sc.delete,
} {
var operations []func() error

// If the syncer is configured to skip deletes, then don't add those functions at all to the list of diff operations.
if !sc.noDeletes {
operations = append(operations, sc.deleteDuplicates)
}

operations = append(operations, sc.createUpdate)

if !sc.noDeletes {
operations = append(operations, sc.delete)
}

for _, operation := range operations {
err := operation()
if err != nil {
return err
Expand Down
133 changes: 133 additions & 0 deletions tests/integration/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
package integration

import (
"context"
"testing"

"github.com/kong/go-database-reconciler/pkg/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

deckDiff "github.com/kong/go-database-reconciler/pkg/diff"
deckDump "github.com/kong/go-database-reconciler/pkg/dump"
)

var (
Expand Down Expand Up @@ -1824,3 +1829,131 @@ func Test_Diff_PluginUpdate_OlderThan38x(t *testing.T) {
})
}
}

func Test_Diff_NoDeletes_OlderThan3x(t *testing.T) {
tests := []struct {
name string
initialStateFile string
stateFile string
expectedState utils.KongRawState
envVars map[string]string
noDeletes bool
expectedDeleteCount int32
}{
{
name: "deleted plugins show in the diff by default",
initialStateFile: "testdata/diff/006-no-deletes/01-plugin-removed-initial.yaml",
stateFile: "testdata/diff/006-no-deletes/01-plugin-removed-current.yaml",
envVars: diffEnvVars,
noDeletes: false,
expectedDeleteCount: 1,
},
{
name: "deleted plugins do not show in the diff",
initialStateFile: "testdata/diff/006-no-deletes/01-plugin-removed-initial.yaml",
stateFile: "testdata/diff/006-no-deletes/01-plugin-removed-current.yaml",
envVars: diffEnvVars,
noDeletes: true,
expectedDeleteCount: 0,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
for k, v := range tc.envVars {
t.Setenv(k, v)
}
runWhen(t, "kong", "==2.8.0")
setup(t)

// initialize state
assert.NoError(t, sync(tc.initialStateFile))

client, err := getTestClient()
ctx := context.Background()

currentState, err := fetchCurrentState(ctx, client, deckDump.Config{IncludeLicenses: true})
require.NoError(t, err)

targetState := stateFromFile(ctx, t, tc.stateFile, client, deckDump.Config{
IncludeLicenses: true,
})

syncer, err := deckDiff.NewSyncer(deckDiff.SyncerOpts{
CurrentState: currentState,
TargetState: targetState,

KongClient: client,
IncludeLicenses: true,
NoDeletes: tc.noDeletes,
})

stats, errs, _ := syncer.Solve(ctx, 1, false, true)
assert.Equal(t, 0, len(errs))
assert.Equal(t, tc.expectedDeleteCount, stats.DeleteOps.Count())
})
}
}

func Test_Diff_NoDeletes_3x(t *testing.T) {
tests := []struct {
name string
initialStateFile string
stateFile string
expectedState utils.KongRawState
envVars map[string]string
noDeletes bool
expectedDeleteCount int32
}{
{
name: "deleted plugins show in the diff by default",
initialStateFile: "testdata/diff/006-no-deletes/01-plugin-removed-initial.yaml",
stateFile: "testdata/diff/006-no-deletes/01-plugin-removed-current.yaml",
envVars: diffEnvVars,
noDeletes: false,
expectedDeleteCount: 1,
},
{
name: "deleted plugins do not show in the diff",
initialStateFile: "testdata/diff/006-no-deletes/01-plugin-removed-initial.yaml",
stateFile: "testdata/diff/006-no-deletes/01-plugin-removed-current.yaml",
envVars: diffEnvVars,
noDeletes: true,
expectedDeleteCount: 0,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
for k, v := range tc.envVars {
t.Setenv(k, v)
}
runWhen(t, "kong", ">=3.0.0")
setup(t)

// initialize state
assert.NoError(t, sync(tc.initialStateFile))

client, err := getTestClient()
ctx := context.Background()

currentState, err := fetchCurrentState(ctx, client, deckDump.Config{IncludeLicenses: true})
require.NoError(t, err)

targetState := stateFromFile(ctx, t, tc.stateFile, client, deckDump.Config{
IncludeLicenses: true,
})

syncer, err := deckDiff.NewSyncer(deckDiff.SyncerOpts{
CurrentState: currentState,
TargetState: targetState,

KongClient: client,
IncludeLicenses: true,
NoDeletes: tc.noDeletes,
})

stats, errs, _ := syncer.Solve(ctx, 1, false, true)
assert.Equal(t, 0, len(errs))
assert.Equal(t, tc.expectedDeleteCount, stats.DeleteOps.Count())
})
}
}
8 changes: 4 additions & 4 deletions tests/integration/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func testKongState(t *testing.T, client *kong.Client, isKonnect bool,

func reset(t *testing.T, opts ...string) {
deckCmd := cmd.NewRootCmd()
args := []string{"reset", "--force"}
args := []string{"gateway", "reset", "--force"}
if len(opts) > 0 {
args = append(args, opts...)
}
Expand Down Expand Up @@ -278,7 +278,7 @@ func setup(t *testing.T) {

func sync(kongFile string, opts ...string) error {
deckCmd := cmd.NewRootCmd()
args := []string{"sync", "-s", kongFile}
args := []string{"gateway", "sync", kongFile}
if len(opts) > 0 {
args = append(args, opts...)
}
Expand All @@ -288,7 +288,7 @@ func sync(kongFile string, opts ...string) error {

func diff(kongFile string, opts ...string) (string, error) {
deckCmd := cmd.NewRootCmd()
args := []string{"diff", "-s", kongFile}
args := []string{"gateway", "diff", kongFile}
if len(opts) > 0 {
args = append(args, opts...)
}
Expand All @@ -310,7 +310,7 @@ func diff(kongFile string, opts ...string) (string, error) {

func dump(opts ...string) (string, error) {
deckCmd := cmd.NewRootCmd()
args := []string{"dump"}
args := []string{"gateway", "dump"}
if len(opts) > 0 {
args = append(args, opts...)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
_format_version: "3.0"
services:
- name: svc1
id: 9ecf5708-f2f4-444e-a4c7-fcd3a57f9a6d
host: mockbin.org
tags:
- test
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
_format_version: "3.0"
services:
- name: svc1
id: 9ecf5708-f2f4-444e-a4c7-fcd3a57f9a6d
host: mockbin.org
tags:
- test
plugins:
- id: 777496e1-8b35-4512-ad30-51f9fe5d3147
name: key-auth
enabled: true
config:
hide_credentials: true
Loading