[NET-6444] Add tenancy to Reaper Tests (#19550)

This commit is contained in:
Kumar Kavish 2023-11-10 01:14:33 +05:30 committed by GitHub
parent f09dbb99e9
commit 3df8b58479
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 174 additions and 149 deletions

View File

@ -4,6 +4,7 @@
package reaper
import (
"github.com/hashicorp/consul/internal/resource/resourcetest"
"testing"
"time"
@ -20,174 +21,198 @@ import (
)
func TestReconcile_ResourceWithNoChildren(t *testing.T) {
client := svctest.RunResourceService(t, demo.RegisterTypes)
client := svctest.RunResourceServiceWithTenancies(t, demo.RegisterTypes)
// Seed the database with an artist.
res, err := demo.GenerateV2Artist()
require.NoError(t, err)
ctx := testutil.TestContext(t)
writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
runReaperTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) {
// Seed the database with an artist.
res, err := demo.GenerateV2Artist()
// Delete the artist to create a tombstone
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id})
require.NoError(t, err)
// set resource tenancy from default to test tenancy
res.Id.Tenancy = tenancy
// Retrieve tombstone
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: writeRsp.Resource.Id.Tenancy,
require.NoError(t, err)
ctx := testutil.TestContext(t)
writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
// Delete the artist to create a tombstone
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id})
require.NoError(t, err)
// Retrieve tombstone
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: tenancy,
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, 1)
tombstone := listRsp.Resources[0]
// Verify reconcile does first pass and queues up for a second pass
rec := newReconciler()
runtime := controller.Runtime{
Client: client,
Logger: testutil.Logger(t),
}
req := controller.Request{ID: tombstone.Id}
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
// Verify condition FirstPassCompleted is true
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.NoError(t, err)
tombstone = readRsp.Resource
condition := tombstone.Status[statusKeyReaperController].Conditions[0]
require.Equal(t, conditionTypeFirstPassCompleted, condition.Type)
require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State)
// Verify reconcile does second pass and tombstone is deleted
// Fake out time so elapsed time > secondPassDelay
rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) }
require.NoError(t, rec.Reconcile(ctx, runtime, req))
_, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.Error(t, err)
require.Equal(t, codes.NotFound.String(), status.Code(err).String())
// Reconcile again to verify no-op on an already deleted tombstone
require.NoError(t, rec.Reconcile(ctx, runtime, req))
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, 1)
tombstone := listRsp.Resources[0]
// Verify reconcile does first pass and queues up for a second pass
rec := newReconciler()
runtime := controller.Runtime{
Client: client,
Logger: testutil.Logger(t),
}
req := controller.Request{ID: tombstone.Id}
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
// Verify condition FirstPassCompleted is true
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.NoError(t, err)
tombstone = readRsp.Resource
condition := tombstone.Status[statusKeyReaperController].Conditions[0]
require.Equal(t, conditionTypeFirstPassCompleted, condition.Type)
require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State)
// Verify reconcile does second pass and tombstone is deleted
// Fake out time so elapsed time > secondPassDelay
rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) }
require.NoError(t, rec.Reconcile(ctx, runtime, req))
_, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.Error(t, err)
require.Equal(t, codes.NotFound.String(), status.Code(err).String())
// Reconcile again to verify no-op on an already deleted tombstone
require.NoError(t, rec.Reconcile(ctx, runtime, req))
}
func TestReconcile_ResourceWithChildren(t *testing.T) {
client := svctest.RunResourceService(t, demo.RegisterTypes)
client := svctest.RunResourceServiceWithTenancies(t, demo.RegisterTypes)
// Seed the database with an artist
res, err := demo.GenerateV2Artist()
require.NoError(t, err)
ctx := testutil.TestContext(t)
writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
artist := writeRsp.Resource
runReaperTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) {
// Seed the database with an artist
res, err := demo.GenerateV2Artist()
// set resource tenancy from default to test tenancy
res.Id.Tenancy = tenancy
// Create 3 albums owned by the artist
numAlbums := 3
for i := 0; i < numAlbums; i++ {
res, err = demo.GenerateV2Album(artist.Id)
require.NoError(t, err)
_, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
ctx := testutil.TestContext(t)
writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
}
artist := writeRsp.Resource
// Delete the artist to create a tombstone
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id})
require.NoError(t, err)
// Create 3 albums owned by the artist
numAlbums := 3
for i := 0; i < numAlbums; i++ {
res, err = demo.GenerateV2Album(artist.Id)
require.NoError(t, err)
_, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
}
// Retrieve the tombstone
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: writeRsp.Resource.Id.Tenancy,
// Delete the artist to create a tombstone
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id})
require.NoError(t, err)
// Retrieve the tombstone
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: writeRsp.Resource.Id.Tenancy,
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, 1)
tombstone := listRsp.Resources[0]
// Verify reconcile does first pass delete and queues up for a second pass
rec := newReconciler()
runtime := controller.Runtime{
Client: client,
Logger: testutil.Logger(t),
}
req := controller.Request{ID: tombstone.Id}
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
// Verify 3 albums deleted
listRsp, err = client.List(ctx, &pbresource.ListRequest{
Type: demo.TypeV2Album,
Tenancy: artist.Id.Tenancy,
})
require.NoError(t, err)
require.Empty(t, listRsp.Resources)
// Verify condition FirstPassCompleted is true
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.NoError(t, err)
tombstone = readRsp.Resource
condition := tombstone.Status[statusKeyReaperController].Conditions[0]
require.Equal(t, conditionTypeFirstPassCompleted, condition.Type)
require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State)
// Verify reconcile does second pass
// Fake out time so elapsed time > secondPassDelay
rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) }
require.NoError(t, rec.Reconcile(ctx, runtime, req))
// Verify artist tombstone deleted
_, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.Error(t, err)
require.Equal(t, codes.NotFound.String(), status.Code(err).String())
// Verify tombstones for 3 albums created
listRsp, err = client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: artist.Id.Tenancy,
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, numAlbums)
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, 1)
tombstone := listRsp.Resources[0]
// Verify reconcile does first pass delete and queues up for a second pass
rec := newReconciler()
runtime := controller.Runtime{
Client: client,
Logger: testutil.Logger(t),
}
req := controller.Request{ID: tombstone.Id}
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
// Verify 3 albums deleted
listRsp, err = client.List(ctx, &pbresource.ListRequest{
Type: demo.TypeV2Album,
Tenancy: artist.Id.Tenancy,
})
require.NoError(t, err)
require.Empty(t, listRsp.Resources)
// Verify condition FirstPassCompleted is true
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.NoError(t, err)
tombstone = readRsp.Resource
condition := tombstone.Status[statusKeyReaperController].Conditions[0]
require.Equal(t, conditionTypeFirstPassCompleted, condition.Type)
require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State)
// Verify reconcile does second pass
// Fake out time so elapsed time > secondPassDelay
rec.timeNow = func() time.Time { return time.Now().Add(secondPassDelay + time.Second) }
require.NoError(t, rec.Reconcile(ctx, runtime, req))
// Verify artist tombstone deleted
_, err = client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.Error(t, err)
require.Equal(t, codes.NotFound.String(), status.Code(err).String())
// Verify tombstones for 3 albums created
listRsp, err = client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: artist.Id.Tenancy,
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, numAlbums)
}
func TestReconcile_RequeueWithDelayWhenSecondPassDelayNotElapsed(t *testing.T) {
client := svctest.RunResourceService(t, demo.RegisterTypes)
client := svctest.RunResourceServiceWithTenancies(t, demo.RegisterTypes)
// Seed the database with an artist.
res, err := demo.GenerateV2Artist()
require.NoError(t, err)
ctx := testutil.TestContext(t)
writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
runReaperTestCaseWithTenancies(func(tenancy *pbresource.Tenancy) {
// Seed the database with an artist.
res, err := demo.GenerateV2Artist()
// Delete the artist to create a tombstone
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id})
require.NoError(t, err)
// set resource tenancy from default to test tenancy
res.Id.Tenancy = tenancy
// Retrieve tombstone
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: writeRsp.Resource.Id.Tenancy,
require.NoError(t, err)
ctx := testutil.TestContext(t)
writeRsp, err := client.Write(ctx, &pbresource.WriteRequest{Resource: res})
require.NoError(t, err)
// Delete the artist to create a tombstone
_, err = client.Delete(ctx, &pbresource.DeleteRequest{Id: writeRsp.Resource.Id})
require.NoError(t, err)
// Retrieve tombstone
listRsp, err := client.List(ctx, &pbresource.ListRequest{
Type: resource.TypeV1Tombstone,
Tenancy: writeRsp.Resource.Id.Tenancy,
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, 1)
tombstone := listRsp.Resources[0]
// Verify reconcile does first pass and queues up for a second pass
rec := newReconciler()
runtime := controller.Runtime{
Client: client,
Logger: testutil.Logger(t),
}
req := controller.Request{ID: tombstone.Id}
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
// Verify condition FirstPassCompleted is true
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.NoError(t, err)
tombstone = readRsp.Resource
condition := tombstone.Status[statusKeyReaperController].Conditions[0]
require.Equal(t, conditionTypeFirstPassCompleted, condition.Type)
require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State)
// Verify requeued for second pass since secondPassDelay time has not elapsed
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
})
require.NoError(t, err)
require.Len(t, listRsp.Resources, 1)
tombstone := listRsp.Resources[0]
// Verify reconcile does first pass and queues up for a second pass
rec := newReconciler()
runtime := controller.Runtime{
Client: client,
Logger: testutil.Logger(t),
}
req := controller.Request{ID: tombstone.Id}
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
// Verify condition FirstPassCompleted is true
readRsp, err := client.Read(ctx, &pbresource.ReadRequest{Id: tombstone.Id})
require.NoError(t, err)
tombstone = readRsp.Resource
condition := tombstone.Status[statusKeyReaperController].Conditions[0]
require.Equal(t, conditionTypeFirstPassCompleted, condition.Type)
require.Equal(t, pbresource.Condition_STATE_TRUE, condition.State)
// Verify requeued for second pass since secondPassDelay time has not elapsed
require.ErrorIs(t, controller.RequeueAfterError(secondPassDelay), rec.Reconcile(ctx, runtime, req))
}
func runReaperTestCaseWithTenancies(testCase func(tenancy *pbresource.Tenancy)) {
for _, tenancy := range resourcetest.TestTenancies() {
testCase(tenancy)
}
}