mirror of https://github.com/fluxcd/cli-utils.git
Add ObjMetadataSet to encapsulate set functions
- Refactor usages of []ObjMetadata to use ObjMetadataSet - Move Union, Diff, Contains, Hash, Remove, and Equal into ObjMetadataSet - Add ToStringMap and FromStringMap for inventory serialization
This commit is contained in:
parent
2a6b353b46
commit
d83ce93efd
|
|
@ -121,7 +121,7 @@ func (ef *formatter) FormatActionGroupEvent(age event.ActionGroupEvent, ags []ev
|
|||
for id, se := range c.LatestStatus() {
|
||||
// Only print information about objects that we actually care about
|
||||
// for this wait task.
|
||||
if found := object.ObjMetas(ag.Identifiers).Contains(id); found {
|
||||
if found := ag.Identifiers.Contains(id); found {
|
||||
ef.printResourceStatus(id, se)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ func (jf *formatter) FormatActionGroupEvent(age event.ActionGroupEvent, ags []ev
|
|||
for id, se := range c.LatestStatus() {
|
||||
// Only print information about objects that we actually care about
|
||||
// for this wait task.
|
||||
if found := object.ObjMetas(ag.Identifiers).Contains(id); found {
|
||||
if found := ag.Identifiers.Contains(id); found {
|
||||
if err := jf.printResourceStatus(se); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func TestResourceStateCollector_New(t *testing.T) {
|
|||
resourceGroups: []event.ActionGroup{
|
||||
{
|
||||
Action: event.ApplyAction,
|
||||
Identifiers: []object.ObjMetadata{
|
||||
Identifiers: object.ObjMetadataSet{
|
||||
depID, customID,
|
||||
},
|
||||
},
|
||||
|
|
@ -64,13 +64,13 @@ func TestResourceStateCollector_New(t *testing.T) {
|
|||
resourceGroups: []event.ActionGroup{
|
||||
{
|
||||
Action: event.ApplyAction,
|
||||
Identifiers: []object.ObjMetadata{
|
||||
Identifiers: object.ObjMetadataSet{
|
||||
customID,
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: event.PruneAction,
|
||||
Identifiers: []object.ObjMetadata{
|
||||
Identifiers: object.ObjMetadataSet{
|
||||
depID,
|
||||
},
|
||||
},
|
||||
|
|
@ -117,7 +117,7 @@ func TestResourceStateCollector_ProcessStatusEvent(t *testing.T) {
|
|||
resourceGroups: []event.ActionGroup{
|
||||
{
|
||||
Action: event.ApplyAction,
|
||||
Identifiers: []object.ObjMetadata{depID},
|
||||
Identifiers: object.ObjMetadataSet{depID},
|
||||
},
|
||||
},
|
||||
statusEvent: event.StatusEvent{
|
||||
|
|
@ -130,7 +130,7 @@ func TestResourceStateCollector_ProcessStatusEvent(t *testing.T) {
|
|||
resourceGroups: []event.ActionGroup{
|
||||
{
|
||||
Action: event.ApplyAction,
|
||||
Identifiers: []object.ObjMetadata{
|
||||
Identifiers: object.ObjMetadataSet{
|
||||
depID, customID,
|
||||
},
|
||||
},
|
||||
|
|
@ -146,13 +146,13 @@ func TestResourceStateCollector_ProcessStatusEvent(t *testing.T) {
|
|||
resourceGroups: []event.ActionGroup{
|
||||
{
|
||||
Action: event.ApplyAction,
|
||||
Identifiers: []object.ObjMetadata{
|
||||
Identifiers: object.ObjMetadataSet{
|
||||
customID,
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: event.PruneAction,
|
||||
Identifiers: []object.ObjMetadata{
|
||||
Identifiers: object.ObjMetadataSet{
|
||||
depID,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func TestStatusCommand(t *testing.T) {
|
|||
printer string
|
||||
timeout time.Duration
|
||||
input string
|
||||
inventory []object.ObjMetadata
|
||||
inventory object.ObjMetadataSet
|
||||
events []pollevent.Event
|
||||
expectedErrMsg string
|
||||
expectedOutput string
|
||||
|
|
@ -76,7 +76,7 @@ func TestStatusCommand(t *testing.T) {
|
|||
pollUntil: "known",
|
||||
printer: "events",
|
||||
input: inventoryTemplate,
|
||||
inventory: []object.ObjMetadata{
|
||||
inventory: object.ObjMetadataSet{
|
||||
depObject,
|
||||
stsObject,
|
||||
},
|
||||
|
|
@ -107,7 +107,7 @@ statefulset.apps/bar is Current: current
|
|||
pollUntil: "current",
|
||||
printer: "events",
|
||||
input: inventoryTemplate,
|
||||
inventory: []object.ObjMetadata{
|
||||
inventory: object.ObjMetadataSet{
|
||||
depObject,
|
||||
stsObject,
|
||||
},
|
||||
|
|
@ -156,7 +156,7 @@ deployment.apps/foo is Current: current
|
|||
pollUntil: "deleted",
|
||||
printer: "events",
|
||||
input: inventoryTemplate,
|
||||
inventory: []object.ObjMetadata{
|
||||
inventory: object.ObjMetadataSet{
|
||||
depObject,
|
||||
stsObject,
|
||||
},
|
||||
|
|
@ -188,7 +188,7 @@ deployment.apps/foo is NotFound: notFound
|
|||
printer: "events",
|
||||
timeout: 2 * time.Second,
|
||||
input: inventoryTemplate,
|
||||
inventory: []object.ObjMetadata{
|
||||
inventory: object.ObjMetadataSet{
|
||||
depObject,
|
||||
stsObject,
|
||||
},
|
||||
|
|
@ -261,7 +261,7 @@ type fakePoller struct {
|
|||
events []pollevent.Event
|
||||
}
|
||||
|
||||
func (f *fakePoller) Poll(ctx context.Context, _ []object.ObjMetadata,
|
||||
func (f *fakePoller) Poll(ctx context.Context, _ object.ObjMetadataSet,
|
||||
_ polling.Options) <-chan pollevent.Event {
|
||||
eventChannel := make(chan pollevent.Event)
|
||||
go func() {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func NewEventPrinter(ioStreams genericclioptions.IOStreams) *eventPrinter {
|
|||
// until the channel is closed. The provided cancelFunc is consulted on
|
||||
// every event and is responsible for stopping the poller when appropriate.
|
||||
// This function will block.
|
||||
func (ep *eventPrinter) Print(ch <-chan pollevent.Event, identifiers []object.ObjMetadata,
|
||||
func (ep *eventPrinter) Print(ch <-chan pollevent.Event, identifiers object.ObjMetadataSet,
|
||||
cancelFunc collector.ObserverFunc) error {
|
||||
coll := collector.NewResourceStatusCollector(identifiers)
|
||||
// The actual work is done by the collector, which will invoke the
|
||||
|
|
|
|||
|
|
@ -21,5 +21,5 @@ type Printer interface {
|
|||
// needs to, and that it has completed shutting down. The latter is important
|
||||
// to make sure the printer has a chance to output all data before the
|
||||
// program terminates.
|
||||
Print(ch <-chan event.Event, identifiers []object.ObjMetadata, cancelFunc collector.ObserverFunc) error
|
||||
Print(ch <-chan event.Event, identifiers object.ObjMetadataSet, cancelFunc collector.ObserverFunc) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func NewTablePrinter(ioStreams genericclioptions.IOStreams) *tablePrinter {
|
|||
|
||||
// Print take an event channel and outputs the status events on the channel
|
||||
// until the channel is closed .
|
||||
func (t *tablePrinter) Print(ch <-chan event.Event, identifiers []object.ObjMetadata,
|
||||
func (t *tablePrinter) Print(ch <-chan event.Event, identifiers object.ObjMetadataSet,
|
||||
cancelFunc collector.ObserverFunc) error {
|
||||
coll := collector.NewResourceStatusCollector(identifiers)
|
||||
stop := make(chan struct{})
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ type inventoryInfo struct {
|
|||
name string
|
||||
namespace string
|
||||
id string
|
||||
list []object.ObjMetadata
|
||||
set object.ObjMetadataSet
|
||||
}
|
||||
|
||||
func (i inventoryInfo) toWrapped() inventory.InventoryInfo {
|
||||
|
|
@ -229,7 +229,7 @@ func TestApplier(t *testing.T) {
|
|||
name: "inv-123",
|
||||
namespace: "default",
|
||||
id: "test",
|
||||
list: []object.ObjMetadata{
|
||||
set: object.ObjMetadataSet{
|
||||
object.UnstructuredToObjMetaOrDie(
|
||||
testutil.Unstructured(t, resources["deployment"]),
|
||||
),
|
||||
|
|
@ -302,7 +302,7 @@ func TestApplier(t *testing.T) {
|
|||
name: "inv-123",
|
||||
namespace: "default",
|
||||
id: "test",
|
||||
list: []object.ObjMetadata{
|
||||
set: object.ObjMetadataSet{
|
||||
object.UnstructuredToObjMetaOrDie(
|
||||
testutil.Unstructured(t, resources["deployment"]),
|
||||
),
|
||||
|
|
@ -423,7 +423,7 @@ func TestApplier(t *testing.T) {
|
|||
name: "abc-123",
|
||||
namespace: "default",
|
||||
id: "test",
|
||||
list: []object.ObjMetadata{
|
||||
set: object.ObjMetadataSet{
|
||||
object.UnstructuredToObjMetaOrDie(
|
||||
testutil.Unstructured(t, resources["deployment"]),
|
||||
),
|
||||
|
|
@ -466,7 +466,7 @@ func TestApplier(t *testing.T) {
|
|||
name: "abc-123",
|
||||
namespace: "default",
|
||||
id: "test",
|
||||
list: []object.ObjMetadata{
|
||||
set: object.ObjMetadataSet{
|
||||
object.UnstructuredToObjMetaOrDie(
|
||||
testutil.Unstructured(t, resources["deployment"]),
|
||||
),
|
||||
|
|
@ -540,7 +540,7 @@ func TestApplier(t *testing.T) {
|
|||
inventoryName: tc.invInfo.name,
|
||||
inventoryNamespace: tc.invInfo.namespace,
|
||||
inventoryID: tc.invInfo.id,
|
||||
inventoryList: tc.invInfo.list,
|
||||
inventorySet: tc.invInfo.set,
|
||||
},
|
||||
}, &genericHandler{
|
||||
resources: objs,
|
||||
|
|
@ -851,7 +851,7 @@ type inventoryObjectHandler struct {
|
|||
inventoryName string
|
||||
inventoryNamespace string
|
||||
inventoryID string
|
||||
inventoryList []object.ObjMetadata
|
||||
inventorySet object.ObjMetadataSet
|
||||
inventoryObj *v1.ConfigMap
|
||||
}
|
||||
|
||||
|
|
@ -874,15 +874,11 @@ func (i *inventoryObjectHandler) handle(t *testing.T, req *http.Request) (*http.
|
|||
}
|
||||
if cm.Name == i.inventoryName && cm.Namespace == i.inventoryNamespace {
|
||||
i.inventoryObj = &cm
|
||||
var inventoryList []object.ObjMetadata
|
||||
for s := range cm.Data {
|
||||
objMeta, err := object.ParseObjMetadata(s)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
inventoryList = append(inventoryList, objMeta)
|
||||
inventorySet, err := object.FromStringMap(cm.Data)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
i.inventoryList = inventoryList
|
||||
i.inventorySet = inventorySet
|
||||
|
||||
bodyRC := ioutil.NopCloser(bytes.NewReader(b))
|
||||
var statusCode int
|
||||
|
|
@ -904,7 +900,7 @@ func (i *inventoryObjectHandler) handle(t *testing.T, req *http.Request) (*http.
|
|||
},
|
||||
Items: []v1.ConfigMap{},
|
||||
}
|
||||
if len(i.inventoryList) > 0 {
|
||||
if len(i.inventorySet) > 0 {
|
||||
cmList.Items = append(cmList.Items, i.currentInvObj())
|
||||
}
|
||||
bodyRC := ioutil.NopCloser(bytes.NewReader(toJSONBytes(t, &cmList)))
|
||||
|
|
@ -912,7 +908,7 @@ func (i *inventoryObjectHandler) handle(t *testing.T, req *http.Request) (*http.
|
|||
}
|
||||
|
||||
if req.Method == http.MethodGet && invObjPathRegex.Match([]byte(req.URL.Path)) {
|
||||
if len(i.inventoryList) == 0 {
|
||||
if len(i.inventorySet) == 0 {
|
||||
return &http.Response{StatusCode: http.StatusNotFound, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, true, nil
|
||||
}
|
||||
invObj := i.currentInvObj()
|
||||
|
|
@ -923,10 +919,6 @@ func (i *inventoryObjectHandler) handle(t *testing.T, req *http.Request) (*http.
|
|||
}
|
||||
|
||||
func (i *inventoryObjectHandler) currentInvObj() v1.ConfigMap {
|
||||
inv := make(map[string]string)
|
||||
for _, objMeta := range i.inventoryList {
|
||||
inv[objMeta.String()] = ""
|
||||
}
|
||||
return v1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: v1.SchemeGroupVersion.String(),
|
||||
|
|
@ -939,7 +931,7 @@ func (i *inventoryObjectHandler) currentInvObj() v1.ConfigMap {
|
|||
common.InventoryLabel: i.inventoryID,
|
||||
},
|
||||
},
|
||||
Data: inv,
|
||||
Data: i.inventorySet.ToStringMap(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -977,7 +969,7 @@ type fakePoller struct {
|
|||
events []pollevent.Event
|
||||
}
|
||||
|
||||
func (f *fakePoller) Poll(ctx context.Context, _ []object.ObjMetadata, _ polling.Options) <-chan pollevent.Event {
|
||||
func (f *fakePoller) Poll(ctx context.Context, _ object.ObjMetadataSet, _ polling.Options) <-chan pollevent.Event {
|
||||
eventChannel := make(chan pollevent.Event)
|
||||
go func() {
|
||||
defer close(eventChannel)
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ const (
|
|||
type ActionGroup struct {
|
||||
Name string
|
||||
Action ResourceAction
|
||||
Identifiers []object.ObjMetadata
|
||||
Identifiers object.ObjMetadataSet
|
||||
}
|
||||
|
||||
type ErrorEvent struct {
|
||||
|
|
|
|||
|
|
@ -21,5 +21,5 @@ const DefaultPollInterval = 2 * time.Second
|
|||
// The options allows callers to override some of the settings of the poller,
|
||||
// like the polling frequency and the caching strategy.
|
||||
type Poller interface {
|
||||
Poll(ctx context.Context, identifiers []object.ObjMetadata, options polling.Options) <-chan pollevent.Event
|
||||
Poll(ctx context.Context, identifiers object.ObjMetadataSet, options polling.Options) <-chan pollevent.Event
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ func (po *PruneOptions) GetPruneObjs(inv inventory.InventoryInfo,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pruneIds := object.SetDiff(prevInvIds, localIds)
|
||||
pruneIds := prevInvIds.Diff(localIds)
|
||||
pruneObjs := []*unstructured.Unstructured{}
|
||||
for _, pruneID := range pruneIds {
|
||||
pruneObj, err := po.GetObject(pruneID)
|
||||
|
|
|
|||
|
|
@ -581,7 +581,7 @@ func TestGetPruneObjs(t *testing.T) {
|
|||
expectedIds, err := object.UnstructuredsToObjMetas(tc.expectedObjs)
|
||||
require.NoError(t, err)
|
||||
|
||||
if !object.SetEquals(expectedIds, actualIds) {
|
||||
if !object.ObjMetadataSetEquals(expectedIds, actualIds) {
|
||||
t.Errorf("expected prune objects (%v), got (%v)", expectedIds, actualIds)
|
||||
}
|
||||
})
|
||||
|
|
@ -615,7 +615,7 @@ func TestPrune_PropagationPolicy(t *testing.T) {
|
|||
t.Run(name, func(t *testing.T) {
|
||||
captureClient := &optionsCaptureNamespaceClient{}
|
||||
po := PruneOptions{
|
||||
InvClient: inventory.NewFakeInventoryClient([]object.ObjMetadata{}),
|
||||
InvClient: inventory.NewFakeInventoryClient(object.ObjMetadataSet{}),
|
||||
Client: &fakeDynamicClient{
|
||||
resourceInterface: captureClient,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ func (t *TaskQueueBuilder) AppendApplyTask(applyObjs []*unstructured.Unstructure
|
|||
|
||||
// AppendInvAddTask appends a task to wait on the passed objects to the task queue.
|
||||
// Returns a pointer to the Builder to chain function calls.
|
||||
func (t *TaskQueueBuilder) AppendWaitTask(waitIds []object.ObjMetadata, condition taskrunner.Condition,
|
||||
func (t *TaskQueueBuilder) AppendWaitTask(waitIds object.ObjMetadataSet, condition taskrunner.Condition,
|
||||
waitTimeout time.Duration) *TaskQueueBuilder {
|
||||
klog.V(2).Infoln("adding wait task")
|
||||
t.tasks = append(t.tasks, taskrunner.NewWaitTask(
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["deployment"]),
|
||||
testutil.ToIdentifier(t, resources["secret"]),
|
||||
},
|
||||
|
|
@ -212,7 +212,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["crd"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -226,7 +226,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-1",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["crontab1"]),
|
||||
testutil.ToIdentifier(t, resources["crontab2"]),
|
||||
},
|
||||
|
|
@ -277,7 +277,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["namespace"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -291,7 +291,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-1",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["pod"]),
|
||||
testutil.ToIdentifier(t, resources["secret"]),
|
||||
},
|
||||
|
|
@ -315,7 +315,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["secret"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -328,7 +328,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-1",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["deployment"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -384,7 +384,7 @@ func TestTaskQueueBuilder_AppendApplyWaitTasks(t *testing.T) {
|
|||
actWaitTask := toWaitTask(t, actualTask)
|
||||
assert.Equal(t, len(expTsk.Ids), len(actWaitTask.Ids))
|
||||
// Order is NOT important for ids stored within task.
|
||||
if !object.SetEquals(expTsk.Ids, actWaitTask.Ids) {
|
||||
if !expTsk.Ids.Equal(actWaitTask.Ids) {
|
||||
t.Errorf("expected wait ids (%v), got (%v)",
|
||||
expTsk.Ids, actWaitTask.Ids)
|
||||
}
|
||||
|
|
@ -457,7 +457,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["pod"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -470,7 +470,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-1",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["secret"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -495,7 +495,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["pod"]),
|
||||
},
|
||||
taskrunner.AllCurrent,
|
||||
|
|
@ -544,7 +544,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["crontab1"]),
|
||||
testutil.ToIdentifier(t, resources["crontab2"]),
|
||||
},
|
||||
|
|
@ -558,7 +558,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-1",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["crd"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -611,7 +611,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-0",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["pod"]),
|
||||
testutil.ToIdentifier(t, resources["secret"]),
|
||||
},
|
||||
|
|
@ -625,7 +625,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
},
|
||||
taskrunner.NewWaitTask(
|
||||
"wait-1",
|
||||
[]object.ObjMetadata{
|
||||
object.ObjMetadataSet{
|
||||
testutil.ToIdentifier(t, resources["namespace"]),
|
||||
},
|
||||
taskrunner.AllCurrent, 1*time.Second,
|
||||
|
|
@ -676,7 +676,7 @@ func TestTaskQueueBuilder_AppendPruneWaitTasks(t *testing.T) {
|
|||
case *taskrunner.WaitTask:
|
||||
actWaitTask := toWaitTask(t, actualTask)
|
||||
assert.Equal(t, len(expTsk.Ids), len(actWaitTask.Ids))
|
||||
if !object.SetEquals(expTsk.Ids, actWaitTask.Ids) {
|
||||
if !expTsk.Ids.Equal(actWaitTask.Ids) {
|
||||
t.Errorf("expected wait ids (%v), got (%v)",
|
||||
expTsk.Ids, actWaitTask.Ids)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ func (a *ApplyTask) Action() event.ResourceAction {
|
|||
return event.ApplyAction
|
||||
}
|
||||
|
||||
func (a *ApplyTask) Identifiers() []object.ObjMetadata {
|
||||
func (a *ApplyTask) Identifiers() object.ObjMetadataSet {
|
||||
return object.UnstructuredsToObjMetasOrDie(a.Objects)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func TestApplyTask_BasicAppliedObjects(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
actual := taskContext.AppliedResources()
|
||||
if !object.SetEquals(expected, actual) {
|
||||
if !actual.Equal(expected) {
|
||||
t.Errorf("expected (%s) inventory resources, got (%s)", expected, actual)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ func (i *DeleteInvTask) Action() event.ResourceAction {
|
|||
return event.InventoryAction
|
||||
}
|
||||
|
||||
func (i *DeleteInvTask) Identifiers() []object.ObjMetadata {
|
||||
return []object.ObjMetadata{}
|
||||
func (i *DeleteInvTask) Identifiers() object.ObjMetadataSet {
|
||||
return object.ObjMetadataSet{}
|
||||
}
|
||||
|
||||
// Start deletes the inventory object from the cluster.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ func TestDeleteInvTask(t *testing.T) {
|
|||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
client := inventory.NewFakeInventoryClient([]object.ObjMetadata{})
|
||||
client := inventory.NewFakeInventoryClient(object.ObjMetadataSet{})
|
||||
client.Err = tc.err
|
||||
eventChannel := make(chan event.Event)
|
||||
resourceCache := cache.NewResourceCacheMap()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func (i *InvAddTask) Action() event.ResourceAction {
|
|||
return event.InventoryAction
|
||||
}
|
||||
|
||||
func (i *InvAddTask) Identifiers() []object.ObjMetadata {
|
||||
func (i *InvAddTask) Identifiers() object.ObjMetadataSet {
|
||||
return object.UnstructuredsToObjMetasOrDie(i.Objects)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,34 +75,34 @@ func TestInvAddTask(t *testing.T) {
|
|||
id3 := object.UnstructuredToObjMetaOrDie(obj3)
|
||||
|
||||
tests := map[string]struct {
|
||||
initialObjs []object.ObjMetadata
|
||||
initialObjs object.ObjMetadataSet
|
||||
applyObjs []*unstructured.Unstructured
|
||||
expectedObjs []object.ObjMetadata
|
||||
expectedObjs object.ObjMetadataSet
|
||||
}{
|
||||
"no initial inventory and no apply objects; no merged inventory": {
|
||||
initialObjs: []object.ObjMetadata{},
|
||||
initialObjs: object.ObjMetadataSet{},
|
||||
applyObjs: []*unstructured.Unstructured{},
|
||||
expectedObjs: []object.ObjMetadata{},
|
||||
expectedObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
"no initial inventory, one apply object; one merged inventory": {
|
||||
initialObjs: []object.ObjMetadata{},
|
||||
initialObjs: object.ObjMetadataSet{},
|
||||
applyObjs: []*unstructured.Unstructured{obj1},
|
||||
expectedObjs: []object.ObjMetadata{id1},
|
||||
expectedObjs: object.ObjMetadataSet{id1},
|
||||
},
|
||||
"one initial inventory, no apply object; one merged inventory": {
|
||||
initialObjs: []object.ObjMetadata{id2},
|
||||
initialObjs: object.ObjMetadataSet{id2},
|
||||
applyObjs: []*unstructured.Unstructured{},
|
||||
expectedObjs: []object.ObjMetadata{id2},
|
||||
expectedObjs: object.ObjMetadataSet{id2},
|
||||
},
|
||||
"one initial inventory, one apply object; one merged inventory": {
|
||||
initialObjs: []object.ObjMetadata{id3},
|
||||
initialObjs: object.ObjMetadataSet{id3},
|
||||
applyObjs: []*unstructured.Unstructured{obj3},
|
||||
expectedObjs: []object.ObjMetadata{id3},
|
||||
expectedObjs: object.ObjMetadataSet{id3},
|
||||
},
|
||||
"three initial inventory, two same objects; three merged inventory": {
|
||||
initialObjs: []object.ObjMetadata{id1, id2, id3},
|
||||
initialObjs: object.ObjMetadataSet{id1, id2, id3},
|
||||
applyObjs: []*unstructured.Unstructured{obj2, obj3},
|
||||
expectedObjs: []object.ObjMetadata{id1, id2, id3},
|
||||
expectedObjs: object.ObjMetadataSet{id1, id2, id3},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ func TestInvAddTask(t *testing.T) {
|
|||
applyIds, err := object.UnstructuredsToObjMetas(tc.applyObjs)
|
||||
require.NoError(t, err)
|
||||
|
||||
if !object.SetEquals(applyIds, task.Identifiers()) {
|
||||
if !task.Identifiers().Equal(applyIds) {
|
||||
t.Errorf("expected task ids (%s), got (%s)", applyIds, task.Identifiers())
|
||||
}
|
||||
task.Start(context)
|
||||
|
|
@ -134,7 +134,7 @@ func TestInvAddTask(t *testing.T) {
|
|||
t.Errorf("unexpected error running InvAddTask: %s", result.Err)
|
||||
}
|
||||
actual, _ := client.GetClusterObjs(nil, common.DryRunNone)
|
||||
if !object.SetEquals(tc.expectedObjs, actual) {
|
||||
if !tc.expectedObjs.Equal(actual) {
|
||||
t.Errorf("expected merged inventory (%s), got (%s)", tc.expectedObjs, actual)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ func (i *InvSetTask) Action() event.ResourceAction {
|
|||
return event.InventoryAction
|
||||
}
|
||||
|
||||
func (i *InvSetTask) Identifiers() []object.ObjMetadata {
|
||||
return []object.ObjMetadata{}
|
||||
func (i *InvSetTask) Identifiers() object.ObjMetadataSet {
|
||||
return object.ObjMetadataSet{}
|
||||
}
|
||||
|
||||
// Start sets the inventory using the resources applied and the
|
||||
|
|
@ -46,7 +46,7 @@ func (i *InvSetTask) Start(taskContext *taskrunner.TaskContext) {
|
|||
// the inventory, then keep it in the inventory so we don't lose
|
||||
// track of it for next apply/prune. An object not found in the cluster
|
||||
// is NOT stored as an apply failure (so it is properly removed from the inventory).
|
||||
applyFailures := []object.ObjMetadata{}
|
||||
applyFailures := object.ObjMetadataSet{}
|
||||
for _, failure := range taskContext.ResourceFailures() {
|
||||
if _, exists := i.PrevInventory[failure]; exists {
|
||||
applyFailures = append(applyFailures, failure)
|
||||
|
|
@ -55,8 +55,8 @@ func (i *InvSetTask) Start(taskContext *taskrunner.TaskContext) {
|
|||
klog.V(4).Infof("keep in inventory %d applied failures", len(applyFailures))
|
||||
pruneFailures := taskContext.PruneFailures()
|
||||
klog.V(4).Infof("set inventory %d prune failures", len(pruneFailures))
|
||||
allApplyObjs := object.Union(appliedObjs, applyFailures)
|
||||
invObjs := object.Union(allApplyObjs, pruneFailures)
|
||||
allApplyObjs := appliedObjs.Union(applyFailures)
|
||||
invObjs := allApplyObjs.Union(pruneFailures)
|
||||
klog.V(4).Infof("set inventory %d total objects", len(invObjs))
|
||||
err := i.InvClient.Replace(i.InvInfo, invObjs, i.DryRun)
|
||||
taskContext.TaskChannel() <- taskrunner.TaskResult{Err: err}
|
||||
|
|
|
|||
|
|
@ -20,91 +20,91 @@ func TestInvSetTask(t *testing.T) {
|
|||
id3 := object.UnstructuredToObjMetaOrDie(obj3)
|
||||
|
||||
tests := map[string]struct {
|
||||
appliedObjs []object.ObjMetadata
|
||||
applyFailures []object.ObjMetadata
|
||||
prevInventory []object.ObjMetadata
|
||||
pruneFailures []object.ObjMetadata
|
||||
expectedObjs []object.ObjMetadata
|
||||
appliedObjs object.ObjMetadataSet
|
||||
applyFailures object.ObjMetadataSet
|
||||
prevInventory object.ObjMetadataSet
|
||||
pruneFailures object.ObjMetadataSet
|
||||
expectedObjs object.ObjMetadataSet
|
||||
}{
|
||||
"no apply objs, no prune failures; no inventory": {
|
||||
appliedObjs: []object.ObjMetadata{},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{},
|
||||
appliedObjs: object.ObjMetadataSet{},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
"one apply objs, no prune failures; one inventory": {
|
||||
appliedObjs: []object.ObjMetadata{id1},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{id1},
|
||||
appliedObjs: object.ObjMetadataSet{id1},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{id1},
|
||||
},
|
||||
"no apply objs, one prune failures; one inventory": {
|
||||
appliedObjs: []object.ObjMetadata{},
|
||||
pruneFailures: []object.ObjMetadata{id1},
|
||||
expectedObjs: []object.ObjMetadata{id1},
|
||||
appliedObjs: object.ObjMetadataSet{},
|
||||
pruneFailures: object.ObjMetadataSet{id1},
|
||||
expectedObjs: object.ObjMetadataSet{id1},
|
||||
},
|
||||
"one apply objs, one prune failures; one inventory": {
|
||||
appliedObjs: []object.ObjMetadata{id3},
|
||||
pruneFailures: []object.ObjMetadata{id3},
|
||||
expectedObjs: []object.ObjMetadata{id3},
|
||||
appliedObjs: object.ObjMetadataSet{id3},
|
||||
pruneFailures: object.ObjMetadataSet{id3},
|
||||
expectedObjs: object.ObjMetadataSet{id3},
|
||||
},
|
||||
"two apply objs, two prune failures; three inventory": {
|
||||
appliedObjs: []object.ObjMetadata{id1, id2},
|
||||
pruneFailures: []object.ObjMetadata{id2, id3},
|
||||
expectedObjs: []object.ObjMetadata{id1, id2, id3},
|
||||
appliedObjs: object.ObjMetadataSet{id1, id2},
|
||||
pruneFailures: object.ObjMetadataSet{id2, id3},
|
||||
expectedObjs: object.ObjMetadataSet{id1, id2, id3},
|
||||
},
|
||||
"no apply objs, no apply failures, no prune failures; no inventory": {
|
||||
appliedObjs: []object.ObjMetadata{},
|
||||
applyFailures: []object.ObjMetadata{id3},
|
||||
prevInventory: []object.ObjMetadata{},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{},
|
||||
appliedObjs: object.ObjMetadataSet{},
|
||||
applyFailures: object.ObjMetadataSet{id3},
|
||||
prevInventory: object.ObjMetadataSet{},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
"one apply failure not in prev inventory; no inventory": {
|
||||
appliedObjs: []object.ObjMetadata{},
|
||||
applyFailures: []object.ObjMetadata{id3},
|
||||
prevInventory: []object.ObjMetadata{},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{},
|
||||
appliedObjs: object.ObjMetadataSet{},
|
||||
applyFailures: object.ObjMetadataSet{id3},
|
||||
prevInventory: object.ObjMetadataSet{},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
"one apply obj, one apply failure not in prev inventory; one inventory": {
|
||||
appliedObjs: []object.ObjMetadata{id2},
|
||||
applyFailures: []object.ObjMetadata{id3},
|
||||
prevInventory: []object.ObjMetadata{},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{id2},
|
||||
appliedObjs: object.ObjMetadataSet{id2},
|
||||
applyFailures: object.ObjMetadataSet{id3},
|
||||
prevInventory: object.ObjMetadataSet{},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{id2},
|
||||
},
|
||||
"one apply obj, one apply failure in prev inventory; one inventory": {
|
||||
appliedObjs: []object.ObjMetadata{id2},
|
||||
applyFailures: []object.ObjMetadata{id3},
|
||||
prevInventory: []object.ObjMetadata{id3},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{id2, id3},
|
||||
appliedObjs: object.ObjMetadataSet{id2},
|
||||
applyFailures: object.ObjMetadataSet{id3},
|
||||
prevInventory: object.ObjMetadataSet{id3},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{id2, id3},
|
||||
},
|
||||
"one apply obj, two apply failures with one in prev inventory; two inventory": {
|
||||
appliedObjs: []object.ObjMetadata{id2},
|
||||
applyFailures: []object.ObjMetadata{id1, id3},
|
||||
prevInventory: []object.ObjMetadata{id3},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{id2, id3},
|
||||
appliedObjs: object.ObjMetadataSet{id2},
|
||||
applyFailures: object.ObjMetadataSet{id1, id3},
|
||||
prevInventory: object.ObjMetadataSet{id3},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{id2, id3},
|
||||
},
|
||||
"three apply failures with two in prev inventory; two inventory": {
|
||||
appliedObjs: []object.ObjMetadata{},
|
||||
applyFailures: []object.ObjMetadata{id1, id2, id3},
|
||||
prevInventory: []object.ObjMetadata{id2, id3},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{id2, id3},
|
||||
appliedObjs: object.ObjMetadataSet{},
|
||||
applyFailures: object.ObjMetadataSet{id1, id2, id3},
|
||||
prevInventory: object.ObjMetadataSet{id2, id3},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{id2, id3},
|
||||
},
|
||||
"three apply failures with three in prev inventory; three inventory": {
|
||||
appliedObjs: []object.ObjMetadata{},
|
||||
applyFailures: []object.ObjMetadata{id1, id2, id3},
|
||||
prevInventory: []object.ObjMetadata{id2, id3, id1},
|
||||
pruneFailures: []object.ObjMetadata{},
|
||||
expectedObjs: []object.ObjMetadata{id2, id1, id3},
|
||||
appliedObjs: object.ObjMetadataSet{},
|
||||
applyFailures: object.ObjMetadataSet{id1, id2, id3},
|
||||
prevInventory: object.ObjMetadataSet{id2, id3, id1},
|
||||
pruneFailures: object.ObjMetadataSet{},
|
||||
expectedObjs: object.ObjMetadataSet{id2, id1, id3},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
client := inventory.NewFakeInventoryClient([]object.ObjMetadata{})
|
||||
client := inventory.NewFakeInventoryClient(object.ObjMetadataSet{})
|
||||
eventChannel := make(chan event.Event)
|
||||
resourceCache := cache.NewResourceCacheMap()
|
||||
context := taskrunner.NewTaskContext(eventChannel, resourceCache)
|
||||
|
|
@ -137,7 +137,7 @@ func TestInvSetTask(t *testing.T) {
|
|||
t.Errorf("unexpected error running InvAddTask: %s", result.Err)
|
||||
}
|
||||
actual, _ := client.GetClusterObjs(nil, common.DryRunNone)
|
||||
if !object.SetEquals(tc.expectedObjs, actual) {
|
||||
if !tc.expectedObjs.Equal(actual) {
|
||||
t.Errorf("expected merged inventory (%s), got (%s)", tc.expectedObjs, actual)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func (p *PruneTask) Action() event.ResourceAction {
|
|||
return action
|
||||
}
|
||||
|
||||
func (p *PruneTask) Identifiers() []object.ObjMetadata {
|
||||
func (p *PruneTask) Identifiers() object.ObjMetadataSet {
|
||||
return object.UnstructuredsToObjMetasOrDie(p.Objects)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func (c Condition) Meets(s status.Status) bool {
|
|||
// conditionMet tests whether the provided Condition holds true for
|
||||
// all resources in the list, according to the ResourceCache.
|
||||
// Resources in the cache older that the applied generation are non-matches.
|
||||
func conditionMet(taskContext *TaskContext, ids []object.ObjMetadata, c Condition) bool {
|
||||
func conditionMet(taskContext *TaskContext, ids object.ObjMetadataSet, c Condition) bool {
|
||||
switch c {
|
||||
case AllCurrent:
|
||||
return allMatchStatus(taskContext, ids, status.CurrentStatus)
|
||||
|
|
@ -52,7 +52,7 @@ func conditionMet(taskContext *TaskContext, ids []object.ObjMetadata, c Conditio
|
|||
|
||||
// allMatchStatus checks whether all of the resources provided have the provided status.
|
||||
// Resources with older generations are considered non-matching.
|
||||
func allMatchStatus(taskContext *TaskContext, ids []object.ObjMetadata, s status.Status) bool {
|
||||
func allMatchStatus(taskContext *TaskContext, ids object.ObjMetadataSet, s status.Status) bool {
|
||||
for _, id := range ids {
|
||||
cached := taskContext.ResourceCache().Get(id)
|
||||
if cached.Status != s {
|
||||
|
|
@ -74,7 +74,7 @@ func allMatchStatus(taskContext *TaskContext, ids []object.ObjMetadata, s status
|
|||
|
||||
// allMatchStatus checks whether none of the resources provided have the provided status.
|
||||
// Resources with older generations are considered matching.
|
||||
func noneMatchStatus(taskContext *TaskContext, ids []object.ObjMetadata, s status.Status) bool {
|
||||
func noneMatchStatus(taskContext *TaskContext, ids object.ObjMetadataSet, s status.Status) bool {
|
||||
for _, id := range ids {
|
||||
cached := taskContext.ResourceCache().Get(id)
|
||||
if cached.Status == s {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func TestCollector_ConditionMet(t *testing.T) {
|
|||
testCases := map[string]struct {
|
||||
cacheContents []cache.ResourceStatus
|
||||
appliedGen map[object.ObjMetadata]int64
|
||||
ids []object.ObjMetadata
|
||||
ids object.ObjMetadataSet
|
||||
condition Condition
|
||||
expectedResult bool
|
||||
}{
|
||||
|
|
@ -78,7 +78,7 @@ func TestCollector_ConditionMet(t *testing.T) {
|
|||
appliedGen: map[object.ObjMetadata]int64{
|
||||
deployment1Meta: 42,
|
||||
},
|
||||
ids: []object.ObjMetadata{
|
||||
ids: object.ObjMetadataSet{
|
||||
deployment1Meta,
|
||||
},
|
||||
condition: AllCurrent,
|
||||
|
|
@ -94,7 +94,7 @@ func TestCollector_ConditionMet(t *testing.T) {
|
|||
appliedGen: map[object.ObjMetadata]int64{
|
||||
deployment1Meta: 42,
|
||||
},
|
||||
ids: []object.ObjMetadata{
|
||||
ids: object.ObjMetadataSet{
|
||||
deployment1Meta,
|
||||
},
|
||||
condition: AllCurrent,
|
||||
|
|
@ -115,7 +115,7 @@ func TestCollector_ConditionMet(t *testing.T) {
|
|||
deployment1Meta: 42,
|
||||
custom1Meta: 0,
|
||||
},
|
||||
ids: []object.ObjMetadata{
|
||||
ids: object.ObjMetadataSet{
|
||||
deployment1Meta,
|
||||
custom1Meta,
|
||||
},
|
||||
|
|
@ -137,7 +137,7 @@ func TestCollector_ConditionMet(t *testing.T) {
|
|||
deployment1Meta: 42,
|
||||
custom1Meta: 5,
|
||||
},
|
||||
ids: []object.ObjMetadata{
|
||||
ids: object.ObjMetadataSet{
|
||||
deployment1Meta,
|
||||
custom1Meta,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ func (tc *TaskContext) ResourceUID(id object.ObjMetadata) (types.UID, bool) {
|
|||
|
||||
// AppliedResources returns all the objects (as ObjMetadata) that
|
||||
// were added as applied resources to the TaskContext.
|
||||
func (tc *TaskContext) AppliedResources() []object.ObjMetadata {
|
||||
all := make([]object.ObjMetadata, 0, len(tc.appliedResources))
|
||||
func (tc *TaskContext) AppliedResources() object.ObjMetadataSet {
|
||||
all := make(object.ObjMetadataSet, 0, len(tc.appliedResources))
|
||||
for r := range tc.appliedResources {
|
||||
all = append(all, r)
|
||||
}
|
||||
|
|
@ -129,8 +129,8 @@ func (tc *TaskContext) CaptureResourceFailure(id object.ObjMetadata) {
|
|||
tc.failedResources[id] = struct{}{}
|
||||
}
|
||||
|
||||
func (tc *TaskContext) ResourceFailures() []object.ObjMetadata {
|
||||
failures := make([]object.ObjMetadata, 0, len(tc.failedResources))
|
||||
func (tc *TaskContext) ResourceFailures() object.ObjMetadataSet {
|
||||
failures := make(object.ObjMetadataSet, 0, len(tc.failedResources))
|
||||
for f := range tc.failedResources {
|
||||
failures = append(failures, f)
|
||||
}
|
||||
|
|
@ -141,8 +141,8 @@ func (tc *TaskContext) CapturePruneFailure(id object.ObjMetadata) {
|
|||
tc.pruneFailures[id] = struct{}{}
|
||||
}
|
||||
|
||||
func (tc *TaskContext) PruneFailures() []object.ObjMetadata {
|
||||
failures := make([]object.ObjMetadata, 0, len(tc.pruneFailures))
|
||||
func (tc *TaskContext) PruneFailures() object.ObjMetadataSet {
|
||||
failures := make(object.ObjMetadataSet, 0, len(tc.pruneFailures))
|
||||
for f := range tc.pruneFailures {
|
||||
failures = append(failures, f)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import (
|
|||
)
|
||||
|
||||
// NewTaskStatusRunner returns a new TaskStatusRunner.
|
||||
func NewTaskStatusRunner(identifiers []object.ObjMetadata, statusPoller poller.Poller, cache cache.ResourceCache) *taskStatusRunner {
|
||||
func NewTaskStatusRunner(identifiers object.ObjMetadataSet, statusPoller poller.Poller, cache cache.ResourceCache) *taskStatusRunner {
|
||||
return &taskStatusRunner{
|
||||
identifiers: identifiers,
|
||||
statusPoller: statusPoller,
|
||||
|
|
@ -31,7 +31,7 @@ func NewTaskStatusRunner(identifiers []object.ObjMetadata, statusPoller poller.P
|
|||
// tasks while at the same time uses the statusPoller to
|
||||
// keep track of the status of the resources.
|
||||
type taskStatusRunner struct {
|
||||
identifiers []object.ObjMetadata
|
||||
identifiers object.ObjMetadataSet
|
||||
statusPoller poller.Poller
|
||||
|
||||
baseRunner *baseRunner
|
||||
|
|
@ -338,7 +338,7 @@ type TaskResult struct {
|
|||
type TimeoutError struct {
|
||||
// Identifiers contains the identifiers of all resources that the
|
||||
// WaitTask was waiting for.
|
||||
Identifiers []object.ObjMetadata
|
||||
Identifiers object.ObjMetadataSet
|
||||
|
||||
// Timeout is the amount of time it took before it timed out.
|
||||
Timeout time.Duration
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ var (
|
|||
|
||||
func TestBaseRunner(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
identifiers []object.ObjMetadata
|
||||
tasks []Task
|
||||
statusEventsDelay time.Duration
|
||||
statusEvents []pollevent.Event
|
||||
|
|
@ -51,7 +50,6 @@ func TestBaseRunner(t *testing.T) {
|
|||
expectedErrorMsg string
|
||||
}{
|
||||
"wait task runs until condition is met": {
|
||||
identifiers: []object.ObjMetadata{depID, cmID},
|
||||
tasks: []Task{
|
||||
&fakeApplyTask{
|
||||
resultEvent: event.Event{
|
||||
|
|
@ -59,7 +57,7 @@ func TestBaseRunner(t *testing.T) {
|
|||
},
|
||||
duration: 3 * time.Second,
|
||||
},
|
||||
NewWaitTask("wait", []object.ObjMetadata{depID, cmID}, AllCurrent,
|
||||
NewWaitTask("wait", object.ObjMetadataSet{depID, cmID}, AllCurrent,
|
||||
1*time.Minute, testutil.NewFakeRESTMapper()),
|
||||
&fakeApplyTask{
|
||||
resultEvent: event.Event{
|
||||
|
|
@ -99,9 +97,8 @@ func TestBaseRunner(t *testing.T) {
|
|||
},
|
||||
},
|
||||
"wait task times out eventually (Unknown)": {
|
||||
identifiers: []object.ObjMetadata{depID, cmID},
|
||||
tasks: []Task{
|
||||
NewWaitTask("wait", []object.ObjMetadata{depID, cmID}, AllCurrent,
|
||||
NewWaitTask("wait", object.ObjMetadataSet{depID, cmID}, AllCurrent,
|
||||
2*time.Second, testutil.NewFakeRESTMapper()),
|
||||
},
|
||||
statusEventsDelay: time.Second,
|
||||
|
|
@ -128,9 +125,8 @@ func TestBaseRunner(t *testing.T) {
|
|||
expectedErrorMsg: "timeout after 2 seconds waiting for 2 resources ([default_cm__ConfigMap default_dep_apps_Deployment]) to reach condition AllCurrent",
|
||||
},
|
||||
"wait task times out eventually (InProgress)": {
|
||||
identifiers: []object.ObjMetadata{depID, cmID},
|
||||
tasks: []Task{
|
||||
NewWaitTask("wait", []object.ObjMetadata{depID, cmID}, AllCurrent,
|
||||
NewWaitTask("wait", object.ObjMetadataSet{depID, cmID}, AllCurrent,
|
||||
2*time.Second, testutil.NewFakeRESTMapper()),
|
||||
},
|
||||
statusEventsDelay: time.Second,
|
||||
|
|
@ -163,7 +159,6 @@ func TestBaseRunner(t *testing.T) {
|
|||
expectedErrorMsg: "timeout after 2 seconds waiting for 2 resources ([default_cm__ConfigMap default_dep_apps_Deployment]) to reach condition AllCurrent",
|
||||
},
|
||||
"tasks run in order": {
|
||||
identifiers: []object.ObjMetadata{},
|
||||
tasks: []Task{
|
||||
&fakeApplyTask{
|
||||
resultEvent: event.Event{
|
||||
|
|
@ -279,7 +274,6 @@ func TestBaseRunnerCancellation(t *testing.T) {
|
|||
testError := fmt.Errorf("this is a test error")
|
||||
|
||||
testCases := map[string]struct {
|
||||
identifiers []object.ObjMetadata
|
||||
tasks []Task
|
||||
statusEventsDelay time.Duration
|
||||
statusEvents []pollevent.Event
|
||||
|
|
@ -288,7 +282,6 @@ func TestBaseRunnerCancellation(t *testing.T) {
|
|||
expectedEventTypes []event.Type
|
||||
}{
|
||||
"cancellation while custom task is running": {
|
||||
identifiers: []object.ObjMetadata{depID},
|
||||
tasks: []Task{
|
||||
&fakeApplyTask{
|
||||
resultEvent: event.Event{
|
||||
|
|
@ -311,9 +304,8 @@ func TestBaseRunnerCancellation(t *testing.T) {
|
|||
},
|
||||
},
|
||||
"cancellation while wait task is running": {
|
||||
identifiers: []object.ObjMetadata{depID},
|
||||
tasks: []Task{
|
||||
NewWaitTask("wait", []object.ObjMetadata{depID}, AllCurrent,
|
||||
NewWaitTask("wait", object.ObjMetadataSet{depID}, AllCurrent,
|
||||
20*time.Second, testutil.NewFakeRESTMapper()),
|
||||
&fakeApplyTask{
|
||||
resultEvent: event.Event{
|
||||
|
|
@ -329,7 +321,6 @@ func TestBaseRunnerCancellation(t *testing.T) {
|
|||
},
|
||||
},
|
||||
"error while custom task is running": {
|
||||
identifiers: []object.ObjMetadata{depID},
|
||||
tasks: []Task{
|
||||
&fakeApplyTask{
|
||||
resultEvent: event.Event{
|
||||
|
|
@ -354,9 +345,8 @@ func TestBaseRunnerCancellation(t *testing.T) {
|
|||
},
|
||||
},
|
||||
"error from status poller while wait task is running": {
|
||||
identifiers: []object.ObjMetadata{depID},
|
||||
tasks: []Task{
|
||||
NewWaitTask("wait", []object.ObjMetadata{depID}, AllCurrent,
|
||||
NewWaitTask("wait", object.ObjMetadataSet{depID}, AllCurrent,
|
||||
20*time.Second, testutil.NewFakeRESTMapper()),
|
||||
&fakeApplyTask{
|
||||
resultEvent: event.Event{
|
||||
|
|
@ -461,8 +451,8 @@ func (f *fakeApplyTask) Action() event.ResourceAction {
|
|||
return event.ApplyAction
|
||||
}
|
||||
|
||||
func (f *fakeApplyTask) Identifiers() []object.ObjMetadata {
|
||||
return []object.ObjMetadata{}
|
||||
func (f *fakeApplyTask) Identifiers() object.ObjMetadataSet {
|
||||
return object.ObjMetadataSet{}
|
||||
}
|
||||
|
||||
func (f *fakeApplyTask) Start(taskContext *TaskContext) {
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ import (
|
|||
type Task interface {
|
||||
Name() string
|
||||
Action() event.ResourceAction
|
||||
Identifiers() []object.ObjMetadata
|
||||
Identifiers() object.ObjMetadataSet
|
||||
Start(taskContext *TaskContext)
|
||||
ClearTimeout()
|
||||
}
|
||||
|
||||
// NewWaitTask creates a new wait task where we will wait until
|
||||
// the resources specifies by ids all meet the specified condition.
|
||||
func NewWaitTask(name string, ids []object.ObjMetadata, cond Condition, timeout time.Duration, mapper meta.RESTMapper) *WaitTask {
|
||||
func NewWaitTask(name string, ids object.ObjMetadataSet, cond Condition, timeout time.Duration, mapper meta.RESTMapper) *WaitTask {
|
||||
// Create the token channel and only add one item.
|
||||
tokenChannel := make(chan struct{}, 1)
|
||||
tokenChannel <- struct{}{}
|
||||
|
|
@ -56,7 +56,7 @@ type WaitTask struct {
|
|||
// name allows providing a name for the task.
|
||||
name string
|
||||
// Ids is the list of resources that we are waiting for.
|
||||
Ids []object.ObjMetadata
|
||||
Ids object.ObjMetadataSet
|
||||
// Condition defines the status we want all resources to reach
|
||||
Condition Condition
|
||||
// Timeout defines how long we are willing to wait for the condition
|
||||
|
|
@ -86,7 +86,7 @@ func (w *WaitTask) Action() event.ResourceAction {
|
|||
return event.WaitAction
|
||||
}
|
||||
|
||||
func (w *WaitTask) Identifiers() []object.ObjMetadata {
|
||||
func (w *WaitTask) Identifiers() object.ObjMetadataSet {
|
||||
return w.Ids
|
||||
}
|
||||
|
||||
|
|
@ -136,8 +136,8 @@ func (w *WaitTask) checkCondition(taskContext *TaskContext) bool {
|
|||
// pending returns the set of resources being waited on excluding
|
||||
// apply/delete failures. This includes resources which are skipped because of
|
||||
// filtering.
|
||||
func (w *WaitTask) pending(taskContext *TaskContext) []object.ObjMetadata {
|
||||
var ids []object.ObjMetadata
|
||||
func (w *WaitTask) pending(taskContext *TaskContext) object.ObjMetadataSet {
|
||||
var ids object.ObjMetadataSet
|
||||
for _, id := range w.Ids {
|
||||
if (w.Condition == AllCurrent && taskContext.ResourceFailed(id)) ||
|
||||
(w.Condition == AllNotFound && taskContext.PruneFailed(id)) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import (
|
|||
)
|
||||
|
||||
func TestWaitTask_TimeoutTriggered(t *testing.T) {
|
||||
task := NewWaitTask("wait", []object.ObjMetadata{}, AllCurrent,
|
||||
task := NewWaitTask("wait", object.ObjMetadataSet{}, AllCurrent,
|
||||
2*time.Second, testutil.NewFakeRESTMapper())
|
||||
|
||||
eventChannel := make(chan event.Event)
|
||||
|
|
@ -39,7 +39,7 @@ func TestWaitTask_TimeoutTriggered(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWaitTask_TimeoutCancelled(t *testing.T) {
|
||||
task := NewWaitTask("wait", []object.ObjMetadata{}, AllCurrent,
|
||||
task := NewWaitTask("wait", object.ObjMetadataSet{}, AllCurrent,
|
||||
2*time.Second, testutil.NewFakeRESTMapper())
|
||||
|
||||
eventChannel := make(chan event.Event)
|
||||
|
|
@ -60,7 +60,7 @@ func TestWaitTask_TimeoutCancelled(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWaitTask_SingleTaskResult(t *testing.T) {
|
||||
task := NewWaitTask("wait", []object.ObjMetadata{}, AllCurrent,
|
||||
task := NewWaitTask("wait", object.ObjMetadataSet{}, AllCurrent,
|
||||
2*time.Second, testutil.NewFakeRESTMapper())
|
||||
|
||||
eventChannel := make(chan event.Event)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ func TestTextForError(t *testing.T) {
|
|||
"timeout error": {
|
||||
err: &taskrunner.TimeoutError{
|
||||
Timeout: 2 * time.Second,
|
||||
Identifiers: []object.ObjMetadata{
|
||||
Identifiers: object.ObjMetadataSet{
|
||||
{
|
||||
GroupKind: schema.GroupKind{
|
||||
Kind: "Deployment",
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ var (
|
|||
// FakeBuilder encapsulates a resource Builder which will hard-code the return
|
||||
// of an inventory object with the encoded past invObjs.
|
||||
type FakeBuilder struct {
|
||||
invObjs []object.ObjMetadata
|
||||
invObjs object.ObjMetadataSet
|
||||
}
|
||||
|
||||
// SetInventoryObjs sets the objects which will be encoded in
|
||||
// an inventory object to be returned when queried for the cluster
|
||||
// inventory object.
|
||||
func (fb *FakeBuilder) SetInventoryObjs(objs []object.ObjMetadata) {
|
||||
func (fb *FakeBuilder) SetInventoryObjs(objs object.ObjMetadataSet) {
|
||||
fb.invObjs = objs
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ func (fb *FakeBuilder) GetBuilder() func() *resource.Builder {
|
|||
|
||||
// fakeClient hard codes the return of an inventory object that encodes the passed
|
||||
// objects into the inventory object when a GET of configmaps is called.
|
||||
func fakeClient(objs []object.ObjMetadata) resource.FakeClientFunc {
|
||||
func fakeClient(objs object.ObjMetadataSet) resource.FakeClientFunc {
|
||||
return func(version schema.GroupVersion) (resource.RESTClient, error) {
|
||||
return &fake.RESTClient{
|
||||
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
|
||||
|
|
@ -94,7 +94,7 @@ func fakeClient(objs []object.ObjMetadata) resource.FakeClientFunc {
|
|||
Name: "inventory",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
Data: objMap(objs),
|
||||
Data: objs.ToStringMap(),
|
||||
}
|
||||
cmList.Items = append(cmList.Items, cm)
|
||||
bodyRC := ioutil.NopCloser(bytes.NewReader(toJSONBytes(&cmList)))
|
||||
|
|
@ -110,12 +110,3 @@ func toJSONBytes(obj runtime.Object) []byte {
|
|||
objBytes, _ := runtime.Encode(unstructured.NewJSONFallbackEncoder(codec), obj)
|
||||
return objBytes
|
||||
}
|
||||
|
||||
func objMap(objs []object.ObjMetadata) map[string]string {
|
||||
objMap := map[string]string{}
|
||||
for _, obj := range objs {
|
||||
objStr := obj.String()
|
||||
objMap[objStr] = ""
|
||||
}
|
||||
return objMap
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
// FakeInventoryClient is a testing implementation of the InventoryClient interface.
|
||||
type FakeInventoryClient struct {
|
||||
Objs []object.ObjMetadata
|
||||
Objs object.ObjMetadataSet
|
||||
Err error
|
||||
}
|
||||
|
||||
|
|
@ -21,14 +21,14 @@ var (
|
|||
_ InventoryClientFactory = FakeInventoryClientFactory{}
|
||||
)
|
||||
|
||||
type FakeInventoryClientFactory []object.ObjMetadata
|
||||
type FakeInventoryClientFactory object.ObjMetadataSet
|
||||
|
||||
func (f FakeInventoryClientFactory) NewInventoryClient(factory cmdutil.Factory) (InventoryClient, error) {
|
||||
return NewFakeInventoryClient(f), nil
|
||||
return NewFakeInventoryClient(object.ObjMetadataSet(f)), nil
|
||||
}
|
||||
|
||||
// NewFakeInventoryClient returns a FakeInventoryClient.
|
||||
func NewFakeInventoryClient(initObjs []object.ObjMetadata) *FakeInventoryClient {
|
||||
func NewFakeInventoryClient(initObjs object.ObjMetadataSet) *FakeInventoryClient {
|
||||
return &FakeInventoryClient{
|
||||
Objs: initObjs,
|
||||
Err: nil,
|
||||
|
|
@ -36,9 +36,9 @@ func NewFakeInventoryClient(initObjs []object.ObjMetadata) *FakeInventoryClient
|
|||
}
|
||||
|
||||
// GetClusterObjs returns currently stored set of objects.
|
||||
func (fic *FakeInventoryClient) GetClusterObjs(InventoryInfo, common.DryRunStrategy) ([]object.ObjMetadata, error) {
|
||||
func (fic *FakeInventoryClient) GetClusterObjs(InventoryInfo, common.DryRunStrategy) (object.ObjMetadataSet, error) {
|
||||
if fic.Err != nil {
|
||||
return []object.ObjMetadata{}, fic.Err
|
||||
return object.ObjMetadataSet{}, fic.Err
|
||||
}
|
||||
return fic.Objs, nil
|
||||
}
|
||||
|
|
@ -46,19 +46,19 @@ func (fic *FakeInventoryClient) GetClusterObjs(InventoryInfo, common.DryRunStrat
|
|||
// Merge stores the passed objects with the current stored cluster inventory
|
||||
// objects. Returns the set difference of the current set of objects minus
|
||||
// the passed set of objects, or an error if one is set up.
|
||||
func (fic *FakeInventoryClient) Merge(_ InventoryInfo, objs []object.ObjMetadata, _ common.DryRunStrategy) ([]object.ObjMetadata, error) {
|
||||
func (fic *FakeInventoryClient) Merge(_ InventoryInfo, objs object.ObjMetadataSet, _ common.DryRunStrategy) (object.ObjMetadataSet, error) {
|
||||
if fic.Err != nil {
|
||||
return []object.ObjMetadata{}, fic.Err
|
||||
return object.ObjMetadataSet{}, fic.Err
|
||||
}
|
||||
diffObjs := object.SetDiff(fic.Objs, objs)
|
||||
fic.Objs = object.Union(fic.Objs, objs)
|
||||
diffObjs := fic.Objs.Diff(objs)
|
||||
fic.Objs = fic.Objs.Union(objs)
|
||||
return diffObjs, nil
|
||||
}
|
||||
|
||||
// Replace the stored cluster inventory objs with the passed obj, or an
|
||||
// error if one is set up.
|
||||
|
||||
func (fic *FakeInventoryClient) Replace(_ InventoryInfo, objs []object.ObjMetadata, _ common.DryRunStrategy) error {
|
||||
func (fic *FakeInventoryClient) Replace(_ InventoryInfo, objs object.ObjMetadataSet, _ common.DryRunStrategy) error {
|
||||
if fic.Err != nil {
|
||||
return fic.Err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,15 +27,15 @@ type InventoryClient interface {
|
|||
// GetCluster returns the set of previously applied objects as ObjMetadata,
|
||||
// or an error if one occurred. This set of previously applied object references
|
||||
// is stored in the inventory objects living in the cluster.
|
||||
GetClusterObjs(inv InventoryInfo, dryRun common.DryRunStrategy) ([]object.ObjMetadata, error)
|
||||
GetClusterObjs(inv InventoryInfo, dryRun common.DryRunStrategy) (object.ObjMetadataSet, error)
|
||||
// Merge applies the union of the passed objects with the currently
|
||||
// stored objects in the inventory object. Returns the slice of
|
||||
// objects which are a set diff (objects to be pruned). Otherwise,
|
||||
// returns an error if one happened.
|
||||
Merge(inv InventoryInfo, objs []object.ObjMetadata, dryRun common.DryRunStrategy) ([]object.ObjMetadata, error)
|
||||
// stored objects in the inventory object. Returns the set of
|
||||
// objects which are not in the passed objects (objects to be pruned).
|
||||
// Otherwise, returns an error if one happened.
|
||||
Merge(inv InventoryInfo, objs object.ObjMetadataSet, dryRun common.DryRunStrategy) (object.ObjMetadataSet, error)
|
||||
// Replace replaces the set of objects stored in the inventory
|
||||
// object with the passed set of objects, or an error if one occurs.
|
||||
Replace(inv InventoryInfo, objs []object.ObjMetadata, dryRun common.DryRunStrategy) error
|
||||
Replace(inv InventoryInfo, objs object.ObjMetadataSet, dryRun common.DryRunStrategy) error
|
||||
// DeleteInventoryObj deletes the passed inventory object from the APIServer.
|
||||
DeleteInventoryObj(inv InventoryInfo, dryRun common.DryRunStrategy) error
|
||||
// ApplyInventoryNamespace applies the Namespace that the inventory object should be in.
|
||||
|
|
@ -94,8 +94,8 @@ func NewInventoryClient(factory cmdutil.Factory,
|
|||
// to prune. Creates the initial cluster inventory object storing the passed
|
||||
// objects if an inventory object does not exist. Returns an error if one
|
||||
// occurred.
|
||||
func (cic *ClusterInventoryClient) Merge(localInv InventoryInfo, objs []object.ObjMetadata, dryRun common.DryRunStrategy) ([]object.ObjMetadata, error) {
|
||||
pruneIds := []object.ObjMetadata{}
|
||||
func (cic *ClusterInventoryClient) Merge(localInv InventoryInfo, objs object.ObjMetadataSet, dryRun common.DryRunStrategy) (object.ObjMetadataSet, error) {
|
||||
pruneIds := object.ObjMetadataSet{}
|
||||
invObj := cic.invToUnstructuredFunc(localInv)
|
||||
clusterInv, err := cic.GetClusterInventoryInfo(localInv, dryRun)
|
||||
if err != nil {
|
||||
|
|
@ -121,12 +121,12 @@ func (cic *ClusterInventoryClient) Merge(localInv InventoryInfo, objs []object.O
|
|||
if err != nil {
|
||||
return pruneIds, err
|
||||
}
|
||||
if object.SetEquals(objs, clusterObjs) {
|
||||
if objs.Equal(clusterObjs) {
|
||||
klog.V(4).Infof("applied objects same as cluster inventory: do nothing")
|
||||
return pruneIds, nil
|
||||
}
|
||||
pruneIds = object.SetDiff(clusterObjs, objs)
|
||||
unionObjs := object.Union(clusterObjs, objs)
|
||||
pruneIds = clusterObjs.Diff(objs)
|
||||
unionObjs := clusterObjs.Union(objs)
|
||||
klog.V(4).Infof("num objects to prune: %d", len(pruneIds))
|
||||
klog.V(4).Infof("num merged objects to store in inventory: %d", len(unionObjs))
|
||||
wrappedInv := cic.InventoryFactoryFunc(clusterInv)
|
||||
|
|
@ -150,7 +150,7 @@ func (cic *ClusterInventoryClient) Merge(localInv InventoryInfo, objs []object.O
|
|||
|
||||
// Replace stores the passed objects in the cluster inventory object, or
|
||||
// an error if one occurred.
|
||||
func (cic *ClusterInventoryClient) Replace(localInv InventoryInfo, objs []object.ObjMetadata, dryRun common.DryRunStrategy) error {
|
||||
func (cic *ClusterInventoryClient) Replace(localInv InventoryInfo, objs object.ObjMetadataSet, dryRun common.DryRunStrategy) error {
|
||||
// Skip entire function for dry-run.
|
||||
if dryRun.ClientOrServerDryRun() {
|
||||
klog.V(4).Infoln("dry-run replace inventory object: not applied")
|
||||
|
|
@ -160,7 +160,7 @@ func (cic *ClusterInventoryClient) Replace(localInv InventoryInfo, objs []object
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if object.SetEquals(objs, clusterObjs) {
|
||||
if objs.Equal(clusterObjs) {
|
||||
klog.V(4).Infof("applied objects same as cluster inventory: do nothing")
|
||||
return nil
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ func (cic *ClusterInventoryClient) Replace(localInv InventoryInfo, objs []object
|
|||
}
|
||||
|
||||
// replaceInventory stores the passed objects into the passed inventory object.
|
||||
func (cic *ClusterInventoryClient) replaceInventory(inv *unstructured.Unstructured, objs []object.ObjMetadata) (*unstructured.Unstructured, error) {
|
||||
func (cic *ClusterInventoryClient) replaceInventory(inv *unstructured.Unstructured, objs object.ObjMetadataSet) (*unstructured.Unstructured, error) {
|
||||
wrappedInv := cic.InventoryFactoryFunc(inv)
|
||||
if err := wrappedInv.Store(objs); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -223,8 +223,8 @@ func (cic *ClusterInventoryClient) deleteInventoryObjsByLabel(inv InventoryInfo,
|
|||
|
||||
// GetClusterObjs returns the objects stored in the cluster inventory object, or
|
||||
// an error if one occurred.
|
||||
func (cic *ClusterInventoryClient) GetClusterObjs(localInv InventoryInfo, dryRun common.DryRunStrategy) ([]object.ObjMetadata, error) {
|
||||
var objs []object.ObjMetadata
|
||||
func (cic *ClusterInventoryClient) GetClusterObjs(localInv InventoryInfo, dryRun common.DryRunStrategy) (object.ObjMetadataSet, error) {
|
||||
var objs object.ObjMetadataSet
|
||||
clusterInv, err := cic.GetClusterInventoryInfo(localInv, dryRun)
|
||||
if err != nil {
|
||||
return objs, err
|
||||
|
|
@ -378,7 +378,7 @@ func (cic *ClusterInventoryClient) mergeClusterInventory(invObjs []*unstructured
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
retainedObjs = object.Union(retainedObjs, mergeObjs)
|
||||
retainedObjs = retainedObjs.Union(mergeObjs)
|
||||
}
|
||||
if err := wrapRetained.Store(retainedObjs); err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -22,29 +22,29 @@ import (
|
|||
func TestGetClusterInventoryInfo(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
inv InventoryInfo
|
||||
localObjs []object.ObjMetadata
|
||||
localObjs object.ObjMetadataSet
|
||||
isError bool
|
||||
}{
|
||||
"Nil local inventory object is an error": {
|
||||
inv: nil,
|
||||
localObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
isError: true,
|
||||
},
|
||||
"Empty local inventory object": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
isError: false,
|
||||
},
|
||||
"Local inventory with a single object": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
},
|
||||
isError: false,
|
||||
},
|
||||
"Local inventory with multiple objects": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info)},
|
||||
|
|
@ -82,7 +82,7 @@ func TestGetClusterInventoryInfo(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("unexpected error received: %s", err)
|
||||
}
|
||||
if !object.SetEquals(tc.localObjs, clusterObjs) {
|
||||
if !tc.localObjs.Equal(clusterObjs) {
|
||||
t.Fatalf("expected cluster objs (%v), got (%v)", tc.localObjs, clusterObjs)
|
||||
}
|
||||
}
|
||||
|
|
@ -93,60 +93,60 @@ func TestGetClusterInventoryInfo(t *testing.T) {
|
|||
func TestMerge(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
localInv InventoryInfo
|
||||
localObjs []object.ObjMetadata
|
||||
clusterObjs []object.ObjMetadata
|
||||
pruneObjs []object.ObjMetadata
|
||||
localObjs object.ObjMetadataSet
|
||||
clusterObjs object.ObjMetadataSet
|
||||
pruneObjs object.ObjMetadataSet
|
||||
isError bool
|
||||
}{
|
||||
"Nil local inventory object is error": {
|
||||
localInv: nil,
|
||||
localObjs: []object.ObjMetadata{},
|
||||
clusterObjs: []object.ObjMetadata{},
|
||||
pruneObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
clusterObjs: object.ObjMetadataSet{},
|
||||
pruneObjs: object.ObjMetadataSet{},
|
||||
isError: true,
|
||||
},
|
||||
"Cluster and local inventories empty: no prune objects; no change": {
|
||||
localInv: copyInventory(),
|
||||
localObjs: []object.ObjMetadata{},
|
||||
clusterObjs: []object.ObjMetadata{},
|
||||
pruneObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
clusterObjs: object.ObjMetadataSet{},
|
||||
pruneObjs: object.ObjMetadataSet{},
|
||||
isError: false,
|
||||
},
|
||||
"Cluster and local inventories same: no prune objects; no change": {
|
||||
localInv: copyInventory(),
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
},
|
||||
clusterObjs: []object.ObjMetadata{
|
||||
clusterObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
},
|
||||
pruneObjs: []object.ObjMetadata{},
|
||||
pruneObjs: object.ObjMetadataSet{},
|
||||
isError: false,
|
||||
},
|
||||
"Cluster two obj, local one: prune obj": {
|
||||
localInv: copyInventory(),
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
},
|
||||
clusterObjs: []object.ObjMetadata{
|
||||
clusterObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info),
|
||||
},
|
||||
pruneObjs: []object.ObjMetadata{
|
||||
pruneObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod3Info),
|
||||
},
|
||||
isError: false,
|
||||
},
|
||||
"Cluster multiple objs, local multiple different objs: prune objs": {
|
||||
localInv: copyInventory(),
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
},
|
||||
clusterObjs: []object.ObjMetadata{
|
||||
clusterObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info)},
|
||||
pruneObjs: []object.ObjMetadata{
|
||||
pruneObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info),
|
||||
},
|
||||
|
|
@ -180,7 +180,7 @@ func TestMerge(t *testing.T) {
|
|||
if !tc.isError && err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !object.SetEquals(tc.pruneObjs, pruneObjs) {
|
||||
if !tc.pruneObjs.Equal(pruneObjs) {
|
||||
t.Errorf("expected (%v) prune objs; got (%v)", tc.pruneObjs, pruneObjs)
|
||||
}
|
||||
})
|
||||
|
|
@ -191,29 +191,29 @@ func TestMerge(t *testing.T) {
|
|||
func TestCreateInventory(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
inv InventoryInfo
|
||||
localObjs []object.ObjMetadata
|
||||
localObjs object.ObjMetadataSet
|
||||
isError bool
|
||||
}{
|
||||
"Nil local inventory object is an error": {
|
||||
inv: nil,
|
||||
localObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
isError: true,
|
||||
},
|
||||
"Empty local inventory object": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
isError: false,
|
||||
},
|
||||
"Local inventory with a single object": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
},
|
||||
isError: false,
|
||||
},
|
||||
"Local inventory with multiple objects": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info)},
|
||||
|
|
@ -267,35 +267,35 @@ func TestCreateInventory(t *testing.T) {
|
|||
|
||||
func TestReplace(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
localObjs []object.ObjMetadata
|
||||
clusterObjs []object.ObjMetadata
|
||||
localObjs object.ObjMetadataSet
|
||||
clusterObjs object.ObjMetadataSet
|
||||
}{
|
||||
"Cluster and local inventories empty": {
|
||||
localObjs: []object.ObjMetadata{},
|
||||
clusterObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
clusterObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
"Cluster and local inventories same": {
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
},
|
||||
clusterObjs: []object.ObjMetadata{
|
||||
clusterObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
},
|
||||
},
|
||||
"Cluster two obj, local one": {
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
},
|
||||
clusterObjs: []object.ObjMetadata{
|
||||
clusterObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info),
|
||||
},
|
||||
},
|
||||
"Cluster multiple objs, local multiple different objs": {
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
},
|
||||
clusterObjs: []object.ObjMetadata{
|
||||
clusterObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info)},
|
||||
|
|
@ -307,11 +307,11 @@ func TestReplace(t *testing.T) {
|
|||
|
||||
// Client and server dry-run do not throw errors.
|
||||
invClient, _ := NewInventoryClient(tf, WrapInventoryObj, InvInfoToConfigMap)
|
||||
err := invClient.Replace(copyInventory(), []object.ObjMetadata{}, common.DryRunClient)
|
||||
err := invClient.Replace(copyInventory(), object.ObjMetadataSet{}, common.DryRunClient)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error received: %s", err)
|
||||
}
|
||||
err = invClient.Replace(copyInventory(), []object.ObjMetadata{}, common.DryRunServer)
|
||||
err = invClient.Replace(copyInventory(), object.ObjMetadataSet{}, common.DryRunServer)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error received: %s", err)
|
||||
}
|
||||
|
|
@ -340,7 +340,7 @@ func TestReplace(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("unexpected error received: %s", err)
|
||||
}
|
||||
if !object.SetEquals(tc.localObjs, actualObjs) {
|
||||
if !tc.localObjs.Equal(actualObjs) {
|
||||
t.Errorf("expected objects (%s), got (%s)", tc.localObjs, actualObjs)
|
||||
}
|
||||
})
|
||||
|
|
@ -350,27 +350,27 @@ func TestReplace(t *testing.T) {
|
|||
func TestGetClusterObjs(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
localInv InventoryInfo
|
||||
clusterObjs []object.ObjMetadata
|
||||
clusterObjs object.ObjMetadataSet
|
||||
isError bool
|
||||
}{
|
||||
"Nil cluster inventory is error": {
|
||||
localInv: nil,
|
||||
clusterObjs: []object.ObjMetadata{},
|
||||
clusterObjs: object.ObjMetadataSet{},
|
||||
isError: true,
|
||||
},
|
||||
"No cluster objs": {
|
||||
localInv: copyInventory(),
|
||||
clusterObjs: []object.ObjMetadata{},
|
||||
clusterObjs: object.ObjMetadataSet{},
|
||||
isError: false,
|
||||
},
|
||||
"Single cluster obj": {
|
||||
localInv: copyInventory(),
|
||||
clusterObjs: []object.ObjMetadata{ignoreErrInfoToObjMeta(pod1Info)},
|
||||
clusterObjs: object.ObjMetadataSet{ignoreErrInfoToObjMeta(pod1Info)},
|
||||
isError: false,
|
||||
},
|
||||
"Multiple cluster objs": {
|
||||
localInv: copyInventory(),
|
||||
clusterObjs: []object.ObjMetadata{ignoreErrInfoToObjMeta(pod1Info), ignoreErrInfoToObjMeta(pod3Info)},
|
||||
clusterObjs: object.ObjMetadataSet{ignoreErrInfoToObjMeta(pod1Info), ignoreErrInfoToObjMeta(pod3Info)},
|
||||
isError: false,
|
||||
},
|
||||
}
|
||||
|
|
@ -397,7 +397,7 @@ func TestGetClusterObjs(t *testing.T) {
|
|||
if !tc.isError && err != nil {
|
||||
t.Fatalf("unexpected error received: %s", err)
|
||||
}
|
||||
if !object.SetEquals(tc.clusterObjs, clusterObjs) {
|
||||
if !tc.clusterObjs.Equal(clusterObjs) {
|
||||
t.Errorf("expected (%v) cluster inventory objs; got (%v)", tc.clusterObjs, clusterObjs)
|
||||
}
|
||||
})
|
||||
|
|
@ -407,25 +407,25 @@ func TestGetClusterObjs(t *testing.T) {
|
|||
func TestDeleteInventoryObj(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
inv InventoryInfo
|
||||
localObjs []object.ObjMetadata
|
||||
localObjs object.ObjMetadataSet
|
||||
}{
|
||||
"Nil local inventory object is an error": {
|
||||
inv: nil,
|
||||
localObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
"Empty local inventory object": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{},
|
||||
localObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
"Local inventory with a single object": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
},
|
||||
},
|
||||
"Local inventory with multiple objects": {
|
||||
inv: localInv,
|
||||
localObjs: []object.ObjMetadata{
|
||||
localObjs: object.ObjMetadataSet{
|
||||
ignoreErrInfoToObjMeta(pod1Info),
|
||||
ignoreErrInfoToObjMeta(pod2Info),
|
||||
ignoreErrInfoToObjMeta(pod3Info)},
|
||||
|
|
@ -477,7 +477,7 @@ func TestDeleteInventoryObj(t *testing.T) {
|
|||
|
||||
type invAndObjs struct {
|
||||
inv InventoryInfo
|
||||
invObjs []object.ObjMetadata
|
||||
invObjs object.ObjMetadataSet
|
||||
}
|
||||
|
||||
func TestMergeInventoryObjs(t *testing.T) {
|
||||
|
|
@ -486,68 +486,68 @@ func TestMergeInventoryObjs(t *testing.T) {
|
|||
pod3Obj := ignoreErrInfoToObjMeta(pod3Info)
|
||||
tests := map[string]struct {
|
||||
invs []invAndObjs
|
||||
expected []object.ObjMetadata
|
||||
expected object.ObjMetadataSet
|
||||
}{
|
||||
"Single inventory object with no inventory is valid": {
|
||||
invs: []invAndObjs{
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{},
|
||||
invObjs: object.ObjMetadataSet{},
|
||||
},
|
||||
},
|
||||
expected: []object.ObjMetadata{},
|
||||
expected: object.ObjMetadataSet{},
|
||||
},
|
||||
"Single inventory object returns same objects": {
|
||||
invs: []invAndObjs{
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod1Obj},
|
||||
invObjs: object.ObjMetadataSet{pod1Obj},
|
||||
},
|
||||
},
|
||||
expected: []object.ObjMetadata{pod1Obj},
|
||||
expected: object.ObjMetadataSet{pod1Obj},
|
||||
},
|
||||
"Two inventories with the same objects returns them": {
|
||||
invs: []invAndObjs{
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod1Obj},
|
||||
invObjs: object.ObjMetadataSet{pod1Obj},
|
||||
},
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod1Obj},
|
||||
invObjs: object.ObjMetadataSet{pod1Obj},
|
||||
},
|
||||
},
|
||||
expected: []object.ObjMetadata{pod1Obj},
|
||||
expected: object.ObjMetadataSet{pod1Obj},
|
||||
},
|
||||
"Two inventories with different retain the union": {
|
||||
invs: []invAndObjs{
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod1Obj},
|
||||
invObjs: object.ObjMetadataSet{pod1Obj},
|
||||
},
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod2Obj},
|
||||
invObjs: object.ObjMetadataSet{pod2Obj},
|
||||
},
|
||||
},
|
||||
expected: []object.ObjMetadata{pod1Obj, pod2Obj},
|
||||
expected: object.ObjMetadataSet{pod1Obj, pod2Obj},
|
||||
},
|
||||
"More than two inventory objects retains all objects": {
|
||||
invs: []invAndObjs{
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod1Obj, pod2Obj},
|
||||
invObjs: object.ObjMetadataSet{pod1Obj, pod2Obj},
|
||||
},
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod2Obj},
|
||||
invObjs: object.ObjMetadataSet{pod2Obj},
|
||||
},
|
||||
{
|
||||
inv: copyInventory(),
|
||||
invObjs: []object.ObjMetadata{pod3Obj},
|
||||
invObjs: object.ObjMetadataSet{pod3Obj},
|
||||
},
|
||||
},
|
||||
expected: []object.ObjMetadata{pod1Obj, pod2Obj, pod3Obj},
|
||||
expected: object.ObjMetadataSet{pod1Obj, pod2Obj, pod3Obj},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -571,7 +571,7 @@ func TestMergeInventoryObjs(t *testing.T) {
|
|||
}
|
||||
wrapped := WrapInventoryObj(retained)
|
||||
mergedObjs, _ := wrapped.Load()
|
||||
if !object.SetEquals(tc.expected, mergedObjs) {
|
||||
if !tc.expected.Equal(mergedObjs) {
|
||||
t.Errorf("expected merged inventory objects (%v), got (%v)", tc.expected, mergedObjs)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ const legacyInvName = "inventory"
|
|||
// operations.
|
||||
type Inventory interface {
|
||||
// Load retrieves the set of object metadata from the inventory object
|
||||
Load() ([]object.ObjMetadata, error)
|
||||
Load() (object.ObjMetadataSet, error)
|
||||
// Store the set of object metadata in the inventory object
|
||||
Store(objs []object.ObjMetadata) error
|
||||
Store(objs object.ObjMetadataSet) error
|
||||
// GetObject returns the object that stores the inventory
|
||||
GetObject() (*unstructured.Unstructured, error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ func copyInventory() InventoryInfo {
|
|||
return WrapInventoryInfoObj(u)
|
||||
}
|
||||
|
||||
func storeObjsInInventory(info InventoryInfo, objs []object.ObjMetadata) *unstructured.Unstructured {
|
||||
func storeObjsInInventory(info InventoryInfo, objs object.ObjMetadataSet) *unstructured.Unstructured {
|
||||
wrapped := WrapInventoryObj(InvInfoToConfigMap(info))
|
||||
_ = wrapped.Store(objs)
|
||||
inv, _ := wrapped.GetObject()
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func InvInfoToConfigMap(inv InventoryInfo) *unstructured.Unstructured {
|
|||
// object metadata (inventory) to and from the wrapped ConfigMap.
|
||||
type InventoryConfigMap struct {
|
||||
inv *unstructured.Unstructured
|
||||
objMetas []object.ObjMetadata
|
||||
objMetas object.ObjMetadataSet
|
||||
}
|
||||
|
||||
var _ InventoryInfo = &InventoryConfigMap{}
|
||||
|
|
@ -72,8 +72,8 @@ func (icm *InventoryConfigMap) UnstructuredInventory() *unstructured.Unstructure
|
|||
|
||||
// Load is an Inventory interface function returning the set of
|
||||
// object metadata from the wrapped ConfigMap, or an error.
|
||||
func (icm *InventoryConfigMap) Load() ([]object.ObjMetadata, error) {
|
||||
objs := []object.ObjMetadata{}
|
||||
func (icm *InventoryConfigMap) Load() (object.ObjMetadataSet, error) {
|
||||
objs := object.ObjMetadataSet{}
|
||||
objMap, exists, err := unstructured.NestedStringMap(icm.inv.Object, "data")
|
||||
if err != nil {
|
||||
err := fmt.Errorf("error retrieving object metadata from inventory object")
|
||||
|
|
@ -94,7 +94,7 @@ func (icm *InventoryConfigMap) Load() ([]object.ObjMetadata, error) {
|
|||
// Store is an Inventory interface function implemented to store
|
||||
// the object metadata in the wrapped ConfigMap. Actual storing
|
||||
// happens in "GetObject".
|
||||
func (icm *InventoryConfigMap) Store(objMetas []object.ObjMetadata) error {
|
||||
func (icm *InventoryConfigMap) Store(objMetas object.ObjMetadataSet) error {
|
||||
icm.objMetas = objMetas
|
||||
return nil
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ func (icm *InventoryConfigMap) GetObject() (*unstructured.Unstructured, error) {
|
|||
return invCopy, nil
|
||||
}
|
||||
|
||||
func buildObjMap(objMetas []object.ObjMetadata) map[string]string {
|
||||
func buildObjMap(objMetas object.ObjMetadataSet) map[string]string {
|
||||
objMap := map[string]string{}
|
||||
for _, objMetadata := range objMetas {
|
||||
objMap[objMetadata.String()] = ""
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ var genGroupKinds = map[schema.GroupKind][]schema.GroupKind{
|
|||
|
||||
// NewCachingClusterReader returns a new instance of the ClusterReader. The
|
||||
// ClusterReader needs will use the clusterreader to fetch resources from the cluster,
|
||||
// while the mapper is used to resolve the version for GroupKinds. The list of
|
||||
// while the mapper is used to resolve the version for GroupKinds. The set of
|
||||
// identifiers is needed so the ClusterReader can figure out which GroupKind
|
||||
// and namespace combinations it needs to cache when the Sync function is called.
|
||||
// We only want to fetch the resources that are actually needed.
|
||||
func NewCachingClusterReader(reader client.Reader, mapper meta.RESTMapper, identifiers []object.ObjMetadata) (*CachingClusterReader, error) {
|
||||
func NewCachingClusterReader(reader client.Reader, mapper meta.RESTMapper, identifiers object.ObjMetadataSet) (*CachingClusterReader, error) {
|
||||
gvkNamespaceSet := newGnSet()
|
||||
for _, id := range identifiers {
|
||||
// For every identifier, add the GroupVersionKind and namespace combination to the gvkNamespaceSet and
|
||||
|
|
|
|||
|
|
@ -30,14 +30,14 @@ var (
|
|||
|
||||
func TestSync(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
identifiers []object.ObjMetadata
|
||||
identifiers object.ObjMetadataSet
|
||||
expectedSynced []gkNamespace
|
||||
}{
|
||||
"no identifiers": {
|
||||
identifiers: []object.ObjMetadata{},
|
||||
identifiers: object.ObjMetadataSet{},
|
||||
},
|
||||
"same GVK in multiple namespaces": {
|
||||
identifiers: []object.ObjMetadata{
|
||||
identifiers: object.ObjMetadataSet{
|
||||
{
|
||||
GroupKind: deploymentGVK.GroupKind(),
|
||||
Name: "deployment",
|
||||
|
|
@ -152,7 +152,7 @@ func TestSync_Errors(t *testing.T) {
|
|||
|
||||
for tn, tc := range testCases {
|
||||
t.Run(tn, func(t *testing.T) {
|
||||
identifiers := []object.ObjMetadata{
|
||||
identifiers := object.ObjMetadataSet{
|
||||
{
|
||||
Name: "my-crd",
|
||||
GroupKind: schema.GroupKind{
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
"sigs.k8s.io/cli-utils/pkg/object"
|
||||
)
|
||||
|
||||
func NewResourceStatusCollector(identifiers []object.ObjMetadata) *ResourceStatusCollector {
|
||||
func NewResourceStatusCollector(identifiers object.ObjMetadataSet) *ResourceStatusCollector {
|
||||
resourceStatuses := make(map[object.ObjMetadata]*event.ResourceStatus)
|
||||
for _, id := range identifiers {
|
||||
resourceStatuses[id] = &event.ResourceStatus{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import (
|
|||
)
|
||||
|
||||
func TestCollectorStopsWhenEventChannelIsClosed(t *testing.T) {
|
||||
var identifiers []object.ObjMetadata
|
||||
var identifiers object.ObjMetadataSet
|
||||
|
||||
collector := NewResourceStatusCollector(identifiers)
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ func TestCollectorStopsWhenEventChannelIsClosed(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCollectorWithFatalError(t *testing.T) {
|
||||
var identifiers []object.ObjMetadata
|
||||
var identifiers object.ObjMetadataSet
|
||||
|
||||
collector := NewResourceStatusCollector(identifiers)
|
||||
|
||||
|
|
@ -91,12 +91,12 @@ var (
|
|||
|
||||
func TestCollectorEventProcessing(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
identifiers []object.ObjMetadata
|
||||
identifiers object.ObjMetadataSet
|
||||
events []event.Event
|
||||
}{
|
||||
"no resources and no events": {},
|
||||
"single resource and single event": {
|
||||
identifiers: []object.ObjMetadata{
|
||||
identifiers: object.ObjMetadataSet{
|
||||
resourceIdentifiers["deployment"],
|
||||
},
|
||||
events: []event.Event{
|
||||
|
|
@ -109,7 +109,7 @@ func TestCollectorEventProcessing(t *testing.T) {
|
|||
},
|
||||
},
|
||||
"multiple resources and multiple events": {
|
||||
identifiers: []object.ObjMetadata{
|
||||
identifiers: object.ObjMetadataSet{
|
||||
resourceIdentifiers["deployment"],
|
||||
resourceIdentifiers["statefulSet"],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import (
|
|||
// ClusterReaderFactoryFunc defines the signature for the function the PollerEngine will use to create
|
||||
// a new ClusterReader for each statusPollerRunner.
|
||||
type ClusterReaderFactoryFunc func(reader client.Reader, mapper meta.RESTMapper,
|
||||
identifiers []object.ObjMetadata) (ClusterReader, error)
|
||||
identifiers object.ObjMetadataSet) (ClusterReader, error)
|
||||
|
||||
// StatusReadersFactoryFunc defines the signature for the function the PollerEngine will use to
|
||||
// create the resource statusReaders and the default engine for each statusPollerRunner.
|
||||
|
|
@ -36,7 +36,7 @@ type PollerEngine struct {
|
|||
// context passed in.
|
||||
// The context can be used to stop the polling process by using timeout, deadline or
|
||||
// cancellation.
|
||||
func (s *PollerEngine) Poll(ctx context.Context, identifiers []object.ObjMetadata, options Options) <-chan event.Event {
|
||||
func (s *PollerEngine) Poll(ctx context.Context, identifiers object.ObjMetadataSet, options Options) <-chan event.Event {
|
||||
eventChannel := make(chan event.Event)
|
||||
|
||||
go func() {
|
||||
|
|
@ -97,7 +97,7 @@ func (s *PollerEngine) validate(options Options) error {
|
|||
|
||||
// validateIdentifiers makes sure that all namespaced resources
|
||||
// passed in
|
||||
func (s *PollerEngine) validateIdentifiers(identifiers []object.ObjMetadata) error {
|
||||
func (s *PollerEngine) validateIdentifiers(identifiers object.ObjMetadataSet) error {
|
||||
for _, id := range identifiers {
|
||||
mapping, err := s.Mapper.RESTMapping(id.GroupKind)
|
||||
if err != nil {
|
||||
|
|
@ -162,9 +162,9 @@ type statusPollerRunner struct {
|
|||
// doesn't have a specific engine in the statusReaders map.
|
||||
defaultStatusReader StatusReader
|
||||
|
||||
// identifiers contains the list of identifiers for the resources that should be polled.
|
||||
// identifiers contains the set of identifiers for the resources that should be polled.
|
||||
// Each resource is identified by GroupKind, namespace and name.
|
||||
identifiers []object.ObjMetadata
|
||||
identifiers object.ObjMetadataSet
|
||||
|
||||
// previousResourceStatuses keeps track of the last event for each
|
||||
// of the polled resources. This is used to make sure we only
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ import (
|
|||
|
||||
func TestStatusPollerRunner(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
identifiers []object.ObjMetadata
|
||||
identifiers object.ObjMetadataSet
|
||||
defaultStatusReader StatusReader
|
||||
expectedEventTypes []event.EventType
|
||||
}{
|
||||
"single resource": {
|
||||
identifiers: []object.ObjMetadata{
|
||||
identifiers: object.ObjMetadataSet{
|
||||
{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
|
|
@ -55,7 +55,7 @@ func TestStatusPollerRunner(t *testing.T) {
|
|||
},
|
||||
},
|
||||
"multiple resources": {
|
||||
identifiers: []object.ObjMetadata{
|
||||
identifiers: object.ObjMetadataSet{
|
||||
{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
|
|
@ -114,7 +114,7 @@ func TestStatusPollerRunner(t *testing.T) {
|
|||
|
||||
options := Options{
|
||||
PollInterval: 2 * time.Second,
|
||||
ClusterReaderFactoryFunc: func(_ client.Reader, _ meta.RESTMapper, _ []object.ObjMetadata) (
|
||||
ClusterReaderFactoryFunc: func(_ client.Reader, _ meta.RESTMapper, _ object.ObjMetadataSet) (
|
||||
ClusterReader, error) {
|
||||
return testutil.NewNoopClusterReader(), nil
|
||||
},
|
||||
|
|
@ -140,7 +140,7 @@ func TestStatusPollerRunner(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewStatusPollerRunnerCancellation(t *testing.T) {
|
||||
identifiers := make([]object.ObjMetadata, 0)
|
||||
identifiers := make(object.ObjMetadataSet, 0)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
|
@ -151,7 +151,7 @@ func TestNewStatusPollerRunnerCancellation(t *testing.T) {
|
|||
|
||||
options := Options{
|
||||
PollInterval: 2 * time.Second,
|
||||
ClusterReaderFactoryFunc: func(_ client.Reader, _ meta.RESTMapper, _ []object.ObjMetadata) (
|
||||
ClusterReaderFactoryFunc: func(_ client.Reader, _ meta.RESTMapper, _ object.ObjMetadataSet) (
|
||||
ClusterReader, error) {
|
||||
return testutil.NewNoopClusterReader(), nil
|
||||
},
|
||||
|
|
@ -176,7 +176,7 @@ func TestNewStatusPollerRunnerCancellation(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNewStatusPollerRunnerIdentifierValidation(t *testing.T) {
|
||||
identifiers := []object.ObjMetadata{
|
||||
identifiers := object.ObjMetadataSet{
|
||||
{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
|
|
@ -193,7 +193,7 @@ func TestNewStatusPollerRunnerIdentifierValidation(t *testing.T) {
|
|||
}
|
||||
|
||||
eventChannel := engine.Poll(context.Background(), identifiers, Options{
|
||||
ClusterReaderFactoryFunc: func(_ client.Reader, _ meta.RESTMapper, _ []object.ObjMetadata) (
|
||||
ClusterReaderFactoryFunc: func(_ client.Reader, _ meta.RESTMapper, _ object.ObjMetadataSet) (
|
||||
ClusterReader, error) {
|
||||
return testutil.NewNoopClusterReader(), nil
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ type StatusPoller struct {
|
|||
// Poll will create a new statusPollerRunner that will poll all the resources provided and report their status
|
||||
// back on the event channel returned. The statusPollerRunner can be cancelled at any time by cancelling the
|
||||
// context passed in.
|
||||
func (s *StatusPoller) Poll(ctx context.Context, identifiers []object.ObjMetadata, options Options) <-chan event.Event {
|
||||
func (s *StatusPoller) Poll(ctx context.Context, identifiers object.ObjMetadataSet, options Options) <-chan event.Event {
|
||||
statusReaderFactory := createStatusReaders
|
||||
if options.CustomStatusReadersFactoryFunc != nil {
|
||||
statusReaderFactory = func(reader engine.ClusterReader, mapper meta.RESTMapper) (map[schema.GroupKind]engine.StatusReader, engine.StatusReader) {
|
||||
|
|
@ -102,7 +102,7 @@ func createStatusReaders(reader engine.ClusterReader, mapper meta.RESTMapper) (m
|
|||
// decided here rather than based on information passed in to the factory function. Thus, the decision
|
||||
// for which implementation is decided when the StatusPoller is created.
|
||||
func clusterReaderFactoryFunc(useCache bool) engine.ClusterReaderFactoryFunc {
|
||||
return func(r client.Reader, mapper meta.RESTMapper, identifiers []object.ObjMetadata) (engine.ClusterReader, error) {
|
||||
return func(r client.Reader, mapper meta.RESTMapper, identifiers object.ObjMetadataSet) (engine.ClusterReader, error) {
|
||||
if useCache {
|
||||
return clusterreader.NewCachingClusterReader(r, mapper, identifiers)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ type fakeLoader struct {
|
|||
|
||||
var _ ManifestLoader = &fakeLoader{}
|
||||
|
||||
func NewFakeLoader(f util.Factory, objs []object.ObjMetadata) *fakeLoader {
|
||||
func NewFakeLoader(f util.Factory, objs object.ObjMetadataSet) *fakeLoader {
|
||||
return &fakeLoader{
|
||||
factory: f,
|
||||
InvClient: inventory.NewFakeInventoryClient(objs),
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import (
|
|||
|
||||
// DependencySet is a set of object references.
|
||||
// When testing equality, order is not importent.
|
||||
type DependencySet []object.ObjMetadata
|
||||
type DependencySet object.ObjMetadataSet
|
||||
|
||||
// Equal returns true if the ObjMetadata sets are equivalent, ignoring order.
|
||||
// Fulfills Equal interface from github.com/google/go-cmp
|
||||
func (a DependencySet) Equal(b DependencySet) bool {
|
||||
return object.SetEquals(a, b)
|
||||
return object.ObjMetadataSet(a).Equal(object.ObjMetadataSet(b))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import (
|
|||
// vertices).
|
||||
type Graph struct {
|
||||
// map "from" vertex -> list of "to" vertices
|
||||
edges map[object.ObjMetadata][]object.ObjMetadata
|
||||
edges map[object.ObjMetadata]object.ObjMetadataSet
|
||||
}
|
||||
|
||||
// Edge encapsulates a pair of vertices describing a
|
||||
|
|
@ -31,7 +31,7 @@ type Edge struct {
|
|||
// New returns a pointer to an empty Graph data structure.
|
||||
func New() *Graph {
|
||||
g := &Graph{}
|
||||
g.edges = make(map[object.ObjMetadata][]object.ObjMetadata)
|
||||
g.edges = make(map[object.ObjMetadata]object.ObjMetadataSet)
|
||||
return g
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ func New() *Graph {
|
|||
// an initial empty set of edges from added vertex.
|
||||
func (g *Graph) AddVertex(v object.ObjMetadata) {
|
||||
if _, exists := g.edges[v]; !exists {
|
||||
g.edges[v] = []object.ObjMetadata{}
|
||||
g.edges[v] = object.ObjMetadataSet{}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,11 +48,11 @@ func (g *Graph) AddVertex(v object.ObjMetadata) {
|
|||
func (g *Graph) AddEdge(from object.ObjMetadata, to object.ObjMetadata) {
|
||||
// Add "from" vertex if it doesn't already exist.
|
||||
if _, exists := g.edges[from]; !exists {
|
||||
g.edges[from] = []object.ObjMetadata{}
|
||||
g.edges[from] = object.ObjMetadataSet{}
|
||||
}
|
||||
// Add "to" vertex if it doesn't already exist.
|
||||
if _, exists := g.edges[to]; !exists {
|
||||
g.edges[to] = []object.ObjMetadata{}
|
||||
g.edges[to] = object.ObjMetadataSet{}
|
||||
}
|
||||
// Add edge "from" -> "to" if it doesn't already exist
|
||||
// into the adjacency list.
|
||||
|
|
@ -100,31 +100,19 @@ func (g *Graph) Size() int {
|
|||
func (g *Graph) removeVertex(r object.ObjMetadata) {
|
||||
// First, remove the object from all adjacency lists.
|
||||
for v, adj := range g.edges {
|
||||
for i, a := range adj {
|
||||
if a == r {
|
||||
g.edges[v] = removeObj(adj, i)
|
||||
break
|
||||
}
|
||||
}
|
||||
g.edges[v] = adj.Remove(r)
|
||||
}
|
||||
// Finally, remove the vertex
|
||||
delete(g.edges, r)
|
||||
}
|
||||
|
||||
// removeObj removes the object at index "i" from the passed
|
||||
// list of vertices, returning the new list.
|
||||
func removeObj(adj []object.ObjMetadata, i int) []object.ObjMetadata {
|
||||
adj[len(adj)-1], adj[i] = adj[i], adj[len(adj)-1]
|
||||
return adj[:len(adj)-1]
|
||||
}
|
||||
|
||||
// Sort returns the ordered set of vertices after
|
||||
// a topological sort.
|
||||
func (g *Graph) Sort() ([][]object.ObjMetadata, error) {
|
||||
sorted := [][]object.ObjMetadata{}
|
||||
func (g *Graph) Sort() ([]object.ObjMetadataSet, error) {
|
||||
sorted := []object.ObjMetadataSet{}
|
||||
for g.Size() > 0 {
|
||||
// Identify all the leaf vertices.
|
||||
leafVertices := []object.ObjMetadata{}
|
||||
leafVertices := object.ObjMetadataSet{}
|
||||
for v, adj := range g.edges {
|
||||
if len(adj) == 0 {
|
||||
leafVertices = append(leafVertices, v)
|
||||
|
|
@ -133,7 +121,7 @@ func (g *Graph) Sort() ([][]object.ObjMetadata, error) {
|
|||
// No leaf vertices means cycle in the directed graph,
|
||||
// where remaining edges define the cycle.
|
||||
if len(leafVertices) == 0 {
|
||||
return [][]object.ObjMetadata{}, CyclicDependencyError{
|
||||
return []object.ObjMetadataSet{}, CyclicDependencyError{
|
||||
Edges: g.GetEdges(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,63 +33,63 @@ var (
|
|||
|
||||
func TestObjectGraphSort(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
vertices []object.ObjMetadata
|
||||
vertices object.ObjMetadataSet
|
||||
edges []Edge
|
||||
expected [][]object.ObjMetadata
|
||||
expected []object.ObjMetadataSet
|
||||
isError bool
|
||||
}{
|
||||
"one edge": {
|
||||
vertices: []object.ObjMetadata{o1, o2},
|
||||
vertices: object.ObjMetadataSet{o1, o2},
|
||||
edges: []Edge{e1},
|
||||
expected: [][]object.ObjMetadata{{o2}, {o1}},
|
||||
expected: []object.ObjMetadataSet{{o2}, {o1}},
|
||||
isError: false,
|
||||
},
|
||||
"two edges": {
|
||||
vertices: []object.ObjMetadata{o1, o2, o3},
|
||||
vertices: object.ObjMetadataSet{o1, o2, o3},
|
||||
edges: []Edge{e1, e2},
|
||||
expected: [][]object.ObjMetadata{{o3}, {o2}, {o1}},
|
||||
expected: []object.ObjMetadataSet{{o3}, {o2}, {o1}},
|
||||
isError: false,
|
||||
},
|
||||
"three edges": {
|
||||
vertices: []object.ObjMetadata{o1, o2, o3},
|
||||
vertices: object.ObjMetadataSet{o1, o2, o3},
|
||||
edges: []Edge{e1, e3, e2},
|
||||
expected: [][]object.ObjMetadata{{o3}, {o2}, {o1}},
|
||||
expected: []object.ObjMetadataSet{{o3}, {o2}, {o1}},
|
||||
isError: false,
|
||||
},
|
||||
"four edges": {
|
||||
vertices: []object.ObjMetadata{o1, o2, o3, o4},
|
||||
vertices: object.ObjMetadataSet{o1, o2, o3, o4},
|
||||
edges: []Edge{e1, e2, e4, e5},
|
||||
expected: [][]object.ObjMetadata{{o4}, {o3}, {o2}, {o1}},
|
||||
expected: []object.ObjMetadataSet{{o4}, {o3}, {o2}, {o1}},
|
||||
isError: false,
|
||||
},
|
||||
"five edges": {
|
||||
vertices: []object.ObjMetadata{o1, o2, o3, o4},
|
||||
vertices: object.ObjMetadataSet{o1, o2, o3, o4},
|
||||
edges: []Edge{e5, e1, e3, e2, e4},
|
||||
expected: [][]object.ObjMetadata{{o4}, {o3}, {o2}, {o1}},
|
||||
expected: []object.ObjMetadataSet{{o4}, {o3}, {o2}, {o1}},
|
||||
isError: false,
|
||||
},
|
||||
"no edges means all in the same first set": {
|
||||
vertices: []object.ObjMetadata{o1, o2, o3, o4},
|
||||
vertices: object.ObjMetadataSet{o1, o2, o3, o4},
|
||||
edges: []Edge{},
|
||||
expected: [][]object.ObjMetadata{{o4, o3, o2, o1}},
|
||||
expected: []object.ObjMetadataSet{{o4, o3, o2, o1}},
|
||||
isError: false,
|
||||
},
|
||||
"multiple objects in first set": {
|
||||
vertices: []object.ObjMetadata{o1, o2, o3, o4, o5},
|
||||
vertices: object.ObjMetadataSet{o1, o2, o3, o4, o5},
|
||||
edges: []Edge{e1, e2, e5, e8},
|
||||
expected: [][]object.ObjMetadata{{o5, o3}, {o4}, {o2}, {o1}},
|
||||
expected: []object.ObjMetadataSet{{o5, o3}, {o4}, {o2}, {o1}},
|
||||
isError: false,
|
||||
},
|
||||
"simple cycle in graph is an error": {
|
||||
vertices: []object.ObjMetadata{o1, o2},
|
||||
vertices: object.ObjMetadataSet{o1, o2},
|
||||
edges: []Edge{e1, e6},
|
||||
expected: [][]object.ObjMetadata{},
|
||||
expected: []object.ObjMetadataSet{},
|
||||
isError: true,
|
||||
},
|
||||
"multi-edge cycle in graph is an error": {
|
||||
vertices: []object.ObjMetadata{o1, o2, o3},
|
||||
vertices: object.ObjMetadataSet{o1, o2, o3},
|
||||
edges: []Edge{e1, e2, e7},
|
||||
expected: [][]object.ObjMetadata{},
|
||||
expected: []object.ObjMetadataSet{},
|
||||
isError: true,
|
||||
},
|
||||
}
|
||||
|
|
@ -116,7 +116,7 @@ func TestObjectGraphSort(t *testing.T) {
|
|||
}
|
||||
for i, actualSet := range actual {
|
||||
expectedSet := tc.expected[i]
|
||||
if !object.SetEquals(expectedSet, actualSet) {
|
||||
if !expectedSet.Equal(actualSet) {
|
||||
t.Errorf("expected sorted objects (%s), got (%s)", tc.expected, actual)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ package object
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
|
|
@ -60,19 +57,6 @@ type ObjMetadata struct {
|
|||
GroupKind schema.GroupKind
|
||||
}
|
||||
|
||||
// ObjMetas is a slice of ObjMetadata.
|
||||
type ObjMetas []ObjMetadata
|
||||
|
||||
// Contains checks if the provided ObjMetadata exists in the ObjMetas slice.
|
||||
func (oms ObjMetas) Contains(id ObjMetadata) bool {
|
||||
for _, om := range oms {
|
||||
if om == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CreateObjMetadata returns an ObjMetadata struct filled
|
||||
// with the passed values. This function normalizes and validates the
|
||||
// passed fields and returns an error for bad parameters.
|
||||
|
|
@ -172,92 +156,3 @@ func RuntimeToObjMeta(obj runtime.Object) (ObjMetadata, error) {
|
|||
return CreateObjMetadata(accessor.GetNamespace(), accessor.GetName(),
|
||||
obj.GetObjectKind().GroupVersionKind().GroupKind())
|
||||
}
|
||||
|
||||
// Hash returns a hash of the sorted strings from
|
||||
// the object metadata, or an error if one occurred.
|
||||
func Hash(objs []ObjMetadata) (string, error) {
|
||||
objStrs := make([]string, 0, len(objs))
|
||||
for _, obj := range objs {
|
||||
objStrs = append(objStrs, obj.String())
|
||||
}
|
||||
hashInt, err := calcHash(objStrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strconv.FormatUint(uint64(hashInt), 16), nil
|
||||
}
|
||||
|
||||
// calcHash returns an unsigned int32 representing the hash
|
||||
// of the obj metadata strings. If there is an error writing bytes to
|
||||
// the hash, then the error is returned; nil is returned otherwise.
|
||||
// Used to quickly identify the set of resources in the inventory object.
|
||||
func calcHash(objs []string) (uint32, error) {
|
||||
sort.Strings(objs)
|
||||
h := fnv.New32a()
|
||||
for _, obj := range objs {
|
||||
_, err := h.Write([]byte(obj))
|
||||
if err != nil {
|
||||
return uint32(0), err
|
||||
}
|
||||
}
|
||||
return h.Sum32(), nil
|
||||
}
|
||||
|
||||
// SetDiff returns the slice of objects that exist in "a", but
|
||||
// do not exist in "b" (A - B).
|
||||
func SetDiff(setA []ObjMetadata, setB []ObjMetadata) []ObjMetadata {
|
||||
// Create a map of the elements of A
|
||||
m := make(map[ObjMetadata]struct{}, len(setA))
|
||||
for _, a := range setA {
|
||||
m[a] = struct{}{}
|
||||
}
|
||||
// Remove from A each element of B
|
||||
for _, b := range setB {
|
||||
delete(m, b) // OK to delete even if b not in m
|
||||
}
|
||||
// Create/return slice from the map of remaining items
|
||||
diff := make([]ObjMetadata, 0, len(m))
|
||||
for r := range m {
|
||||
diff = append(diff, r)
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
// Union returns the slice of objects that is the set of unique
|
||||
// items of the merging of set A and set B.
|
||||
func Union(setA []ObjMetadata, setB []ObjMetadata) []ObjMetadata {
|
||||
m := make(map[ObjMetadata]struct{}, len(setA)+len(setB))
|
||||
for _, a := range setA {
|
||||
m[a] = struct{}{}
|
||||
}
|
||||
for _, b := range setB {
|
||||
m[b] = struct{}{}
|
||||
}
|
||||
union := make([]ObjMetadata, 0, len(m))
|
||||
for u := range m {
|
||||
union = append(union, u)
|
||||
}
|
||||
return union
|
||||
}
|
||||
|
||||
// SetEquals returns true if the slice of objects in setA equals
|
||||
// the slice of objects in setB.
|
||||
func SetEquals(setA []ObjMetadata, setB []ObjMetadata) bool {
|
||||
mapA := make(map[ObjMetadata]struct{}, len(setA))
|
||||
for _, a := range setA {
|
||||
mapA[a] = struct{}{}
|
||||
}
|
||||
mapB := make(map[ObjMetadata]struct{}, len(setB))
|
||||
for _, b := range setB {
|
||||
mapB[b] = struct{}{}
|
||||
}
|
||||
if len(mapA) != len(mapB) {
|
||||
return false
|
||||
}
|
||||
for b := range mapB {
|
||||
if _, exists := mapA[b]; !exists {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,154 @@
|
|||
// Copyright 2021 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"hash/fnv"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ObjMetadataSet is an ordered list of ObjMetadata that acts like an unordered
|
||||
// set for comparison purposes.
|
||||
type ObjMetadataSet []ObjMetadata
|
||||
|
||||
// UnstructuredSetEquals returns true if the slice of objects in setA equals
|
||||
// the slice of objects in setB.
|
||||
func ObjMetadataSetEquals(setA []ObjMetadata, setB []ObjMetadata) bool {
|
||||
return ObjMetadataSet(setA).Equal(ObjMetadataSet(setB))
|
||||
}
|
||||
|
||||
// Equal returns true if the two sets contain equivalent objects. Duplicates are
|
||||
// ignored.
|
||||
// This function satisfies the cmp.Equal interface from github.com/google/go-cmp
|
||||
func (setA ObjMetadataSet) Equal(setB ObjMetadataSet) bool {
|
||||
mapA := make(map[ObjMetadata]struct{}, len(setA))
|
||||
for _, a := range setA {
|
||||
mapA[a] = struct{}{}
|
||||
}
|
||||
mapB := make(map[ObjMetadata]struct{}, len(setB))
|
||||
for _, b := range setB {
|
||||
mapB[b] = struct{}{}
|
||||
}
|
||||
if len(mapA) != len(mapB) {
|
||||
return false
|
||||
}
|
||||
for b := range mapB {
|
||||
if _, exists := mapA[b]; !exists {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Contains checks if the provided ObjMetadata exists in the set.
|
||||
func (setA ObjMetadataSet) Contains(id ObjMetadata) bool {
|
||||
for _, om := range setA {
|
||||
if om == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Remove the object from the set and return the updated set.
|
||||
func (setA ObjMetadataSet) Remove(obj ObjMetadata) ObjMetadataSet {
|
||||
for i, a := range setA {
|
||||
if a == obj {
|
||||
setA[len(setA)-1], setA[i] = setA[i], setA[len(setA)-1]
|
||||
return setA[:len(setA)-1]
|
||||
}
|
||||
}
|
||||
return setA
|
||||
}
|
||||
|
||||
// Union returns the set of unique objects from the merging of set A and set B.
|
||||
func (setA ObjMetadataSet) Union(setB ObjMetadataSet) ObjMetadataSet {
|
||||
m := make(map[ObjMetadata]struct{}, len(setA)+len(setB))
|
||||
for _, a := range setA {
|
||||
m[a] = struct{}{}
|
||||
}
|
||||
for _, b := range setB {
|
||||
m[b] = struct{}{}
|
||||
}
|
||||
union := make(ObjMetadataSet, 0, len(m))
|
||||
for u := range m {
|
||||
union = append(union, u)
|
||||
}
|
||||
return union
|
||||
}
|
||||
|
||||
// Diff returns the set of objects that exist in set A, but not in set B (A - B).
|
||||
func (setA ObjMetadataSet) Diff(setB ObjMetadataSet) ObjMetadataSet {
|
||||
// Create a map of the elements of A
|
||||
m := make(map[ObjMetadata]struct{}, len(setA))
|
||||
for _, a := range setA {
|
||||
m[a] = struct{}{}
|
||||
}
|
||||
// Remove from A each element of B
|
||||
for _, b := range setB {
|
||||
delete(m, b) // OK to delete even if b not in m
|
||||
}
|
||||
// Create/return slice from the map of remaining items
|
||||
diff := make(ObjMetadataSet, 0, len(m))
|
||||
for r := range m {
|
||||
diff = append(diff, r)
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
// Hash the objects in the set by serializing, sorting, concatonating, and
|
||||
// hashing the result with the 32-bit FNV-1a algorithm.
|
||||
func (setA ObjMetadataSet) Hash() (string, error) {
|
||||
objStrs := make([]string, 0, len(setA))
|
||||
for _, obj := range setA {
|
||||
objStrs = append(objStrs, obj.String())
|
||||
}
|
||||
hashInt, err := calcHash(objStrs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strconv.FormatUint(uint64(hashInt), 16), nil
|
||||
}
|
||||
|
||||
// calcHash returns an unsigned int32 representing the hash
|
||||
// of the obj metadata strings. If there is an error writing bytes to
|
||||
// the hash, then the error is returned; nil is returned otherwise.
|
||||
// Used to quickly identify the set of resources in the inventory object.
|
||||
func calcHash(objs []string) (uint32, error) {
|
||||
sort.Strings(objs)
|
||||
h := fnv.New32a()
|
||||
for _, obj := range objs {
|
||||
_, err := h.Write([]byte(obj))
|
||||
if err != nil {
|
||||
return uint32(0), err
|
||||
}
|
||||
}
|
||||
return h.Sum32(), nil
|
||||
}
|
||||
|
||||
// ToStringMap returns the set as a serializable map, with objMeta keys and
|
||||
// empty string values.
|
||||
func (setA ObjMetadataSet) ToStringMap() map[string]string {
|
||||
stringMap := make(map[string]string, len(setA))
|
||||
for _, objMeta := range setA {
|
||||
stringMap[objMeta.String()] = ""
|
||||
}
|
||||
return stringMap
|
||||
}
|
||||
|
||||
// FromStringMap returns a set from a serializable map, with objMeta keys and
|
||||
// empty string values. Errors if parsing fails.
|
||||
func FromStringMap(in map[string]string) (ObjMetadataSet, error) {
|
||||
var set ObjMetadataSet
|
||||
for s := range in {
|
||||
objMeta, err := ParseObjMetadata(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
set = append(set, objMeta)
|
||||
}
|
||||
return set, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
// Copyright 2020 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
var objMeta1 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
var objMeta2 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "StatefulSet",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
var objMeta3 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "",
|
||||
Kind: "Pod",
|
||||
},
|
||||
Name: "pod-a",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
var objMeta4 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "",
|
||||
Kind: "Pod",
|
||||
},
|
||||
Name: "pod-b",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
func TestObjMetadataSetEquals(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
setA ObjMetadataSet
|
||||
setB ObjMetadataSet
|
||||
isEqual bool
|
||||
}{
|
||||
"Empty sets results in empty union": {
|
||||
setA: ObjMetadataSet{},
|
||||
setB: ObjMetadataSet{},
|
||||
isEqual: true,
|
||||
},
|
||||
"Empty second set results in same set": {
|
||||
setA: ObjMetadataSet{objMeta1, objMeta3},
|
||||
setB: ObjMetadataSet{},
|
||||
isEqual: false,
|
||||
},
|
||||
"Empty initial set results in empty diff": {
|
||||
setA: ObjMetadataSet{},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta3},
|
||||
isEqual: false,
|
||||
},
|
||||
"Different ordering are equal sets": {
|
||||
setA: ObjMetadataSet{objMeta2, objMeta1},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta2},
|
||||
isEqual: true,
|
||||
},
|
||||
"One item overlap": {
|
||||
setA: ObjMetadataSet{objMeta2, objMeta1},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta3},
|
||||
isEqual: false,
|
||||
},
|
||||
"Disjoint sets results in larger set": {
|
||||
setA: ObjMetadataSet{objMeta1, objMeta2},
|
||||
setB: ObjMetadataSet{objMeta3, objMeta4},
|
||||
isEqual: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual := tc.setA.Equal(tc.setB)
|
||||
if tc.isEqual != actual {
|
||||
t.Errorf("SetEqual expected (%t), got (%t)", tc.isEqual, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestObjMetadataSetUnion(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
setA ObjMetadataSet
|
||||
setB ObjMetadataSet
|
||||
expected ObjMetadataSet
|
||||
}{
|
||||
"Empty sets results in empty union": {
|
||||
setA: ObjMetadataSet{},
|
||||
setB: ObjMetadataSet{},
|
||||
expected: ObjMetadataSet{},
|
||||
},
|
||||
"Empty second set results in same set": {
|
||||
setA: ObjMetadataSet{objMeta1, objMeta3},
|
||||
setB: ObjMetadataSet{},
|
||||
expected: ObjMetadataSet{objMeta1, objMeta3},
|
||||
},
|
||||
"Empty initial set results in empty diff": {
|
||||
setA: ObjMetadataSet{},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta3},
|
||||
expected: ObjMetadataSet{objMeta1, objMeta3},
|
||||
},
|
||||
"Same sets in different order results in same set": {
|
||||
setA: ObjMetadataSet{objMeta2, objMeta1},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta2},
|
||||
expected: ObjMetadataSet{objMeta1, objMeta2},
|
||||
},
|
||||
"One item overlap": {
|
||||
setA: ObjMetadataSet{objMeta2, objMeta1},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta3},
|
||||
expected: ObjMetadataSet{objMeta1, objMeta2, objMeta3},
|
||||
},
|
||||
"Disjoint sets results in larger set": {
|
||||
setA: ObjMetadataSet{objMeta1, objMeta2},
|
||||
setB: ObjMetadataSet{objMeta3, objMeta4},
|
||||
expected: ObjMetadataSet{objMeta1, objMeta2, objMeta3, objMeta4},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual := tc.setA.Union(tc.setB)
|
||||
if !tc.expected.Equal(actual) {
|
||||
t.Errorf("SetDiff expected set (%s), got (%s)", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestObjMetadataSetDiff(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
setA ObjMetadataSet
|
||||
setB ObjMetadataSet
|
||||
expected ObjMetadataSet
|
||||
}{
|
||||
"Empty sets results in empty diff": {
|
||||
setA: ObjMetadataSet{},
|
||||
setB: ObjMetadataSet{},
|
||||
expected: ObjMetadataSet{},
|
||||
},
|
||||
"Empty subtraction set results in same set": {
|
||||
setA: ObjMetadataSet{objMeta1, objMeta3},
|
||||
setB: ObjMetadataSet{},
|
||||
expected: ObjMetadataSet{objMeta1, objMeta3},
|
||||
},
|
||||
"Empty initial set results in empty diff": {
|
||||
setA: ObjMetadataSet{},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta3},
|
||||
expected: ObjMetadataSet{},
|
||||
},
|
||||
"Sets equal results in empty diff": {
|
||||
setA: ObjMetadataSet{objMeta2, objMeta1},
|
||||
setB: ObjMetadataSet{objMeta1, objMeta2},
|
||||
expected: ObjMetadataSet{},
|
||||
},
|
||||
"Basic diff": {
|
||||
setA: ObjMetadataSet{objMeta2, objMeta1},
|
||||
setB: ObjMetadataSet{objMeta1},
|
||||
expected: ObjMetadataSet{objMeta2},
|
||||
},
|
||||
"Subtract non-elements results in no change": {
|
||||
setA: ObjMetadataSet{objMeta1},
|
||||
setB: ObjMetadataSet{objMeta3, objMeta4},
|
||||
expected: ObjMetadataSet{objMeta1},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual := tc.setA.Diff(tc.setB)
|
||||
if !tc.expected.Equal(actual) {
|
||||
t.Errorf("SetDiff expected set (%s), got (%s)", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestObjMetadataSetHash(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
objs ObjMetadataSet
|
||||
expected string
|
||||
}{
|
||||
"No objects gives valid hash": {
|
||||
objs: ObjMetadataSet{},
|
||||
expected: "811c9dc5",
|
||||
},
|
||||
"Single object gives valid hash": {
|
||||
objs: ObjMetadataSet{objMeta1},
|
||||
expected: "3715cd95",
|
||||
},
|
||||
"Multiple objects gives valid hash": {
|
||||
objs: ObjMetadataSet{objMeta1, objMeta2, objMeta3},
|
||||
expected: "d69d726a",
|
||||
},
|
||||
"Different ordering gives same hash": {
|
||||
objs: ObjMetadataSet{objMeta2, objMeta3, objMeta1},
|
||||
expected: "d69d726a",
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual, err := tc.objs.Hash()
|
||||
if err != nil {
|
||||
t.Fatalf("Received unexpected error: %s", err)
|
||||
}
|
||||
if tc.expected != actual {
|
||||
t.Errorf("expected hash string (%s), got (%s)", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -78,90 +78,6 @@ func TestCreateObjMetadata(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestObjMetadataEquals(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
objMeta1 *ObjMetadata
|
||||
objMeta2 *ObjMetadata
|
||||
expectEquals bool
|
||||
}{
|
||||
"parameter is nil": {
|
||||
objMeta1: &ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
},
|
||||
objMeta2: nil,
|
||||
expectEquals: false,
|
||||
},
|
||||
"different groupKind": {
|
||||
objMeta1: &ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "StatefulSet",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
},
|
||||
objMeta2: &ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
},
|
||||
expectEquals: false,
|
||||
},
|
||||
"both are missing groupKind": {
|
||||
objMeta1: &ObjMetadata{
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
},
|
||||
objMeta2: &ObjMetadata{
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
},
|
||||
expectEquals: true,
|
||||
},
|
||||
"they are equal": {
|
||||
objMeta1: &ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
},
|
||||
objMeta2: &ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
},
|
||||
expectEquals: true,
|
||||
},
|
||||
}
|
||||
|
||||
for tn, tc := range testCases {
|
||||
t.Run(tn, func(t *testing.T) {
|
||||
equal := tc.objMeta1.Equals(tc.objMeta2)
|
||||
|
||||
if tc.expectEquals && !equal {
|
||||
t.Error("Expected objMetas to be equal, but they weren't")
|
||||
}
|
||||
|
||||
if !tc.expectEquals && equal {
|
||||
t.Error("Expected objMetas not to be equal, but they were")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseObjMetadata(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
invStr string
|
||||
|
|
@ -272,219 +188,3 @@ func TestParseObjMetadata(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
var objMeta1 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
var objMeta2 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "apps",
|
||||
Kind: "StatefulSet",
|
||||
},
|
||||
Name: "dep",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
var objMeta3 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "",
|
||||
Kind: "Pod",
|
||||
},
|
||||
Name: "pod-a",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
var objMeta4 = ObjMetadata{
|
||||
GroupKind: schema.GroupKind{
|
||||
Group: "",
|
||||
Kind: "Pod",
|
||||
},
|
||||
Name: "pod-b",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
objs []ObjMetadata
|
||||
expected string
|
||||
}{
|
||||
"No objects gives valid hash": {
|
||||
objs: []ObjMetadata{},
|
||||
expected: "811c9dc5",
|
||||
},
|
||||
"Single object gives valid hash": {
|
||||
objs: []ObjMetadata{objMeta1},
|
||||
expected: "3715cd95",
|
||||
},
|
||||
"Multiple objects gives valid hash": {
|
||||
objs: []ObjMetadata{objMeta1, objMeta2, objMeta3},
|
||||
expected: "d69d726a",
|
||||
},
|
||||
"Different ordering gives same hash": {
|
||||
objs: []ObjMetadata{objMeta2, objMeta3, objMeta1},
|
||||
expected: "d69d726a",
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual, err := Hash(tc.objs)
|
||||
if err != nil {
|
||||
t.Fatalf("Received unexpected error: %s", err)
|
||||
}
|
||||
if tc.expected != actual {
|
||||
t.Errorf("expected hash string (%s), got (%s)", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDiff(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
setA []ObjMetadata
|
||||
setB []ObjMetadata
|
||||
expected []ObjMetadata
|
||||
}{
|
||||
"Empty sets results in empty diff": {
|
||||
setA: []ObjMetadata{},
|
||||
setB: []ObjMetadata{},
|
||||
expected: []ObjMetadata{},
|
||||
},
|
||||
"Empty subtraction set results in same set": {
|
||||
setA: []ObjMetadata{objMeta1, objMeta3},
|
||||
setB: []ObjMetadata{},
|
||||
expected: []ObjMetadata{objMeta1, objMeta3},
|
||||
},
|
||||
"Empty initial set results in empty diff": {
|
||||
setA: []ObjMetadata{},
|
||||
setB: []ObjMetadata{objMeta1, objMeta3},
|
||||
expected: []ObjMetadata{},
|
||||
},
|
||||
"Sets equal results in empty diff": {
|
||||
setA: []ObjMetadata{objMeta2, objMeta1},
|
||||
setB: []ObjMetadata{objMeta1, objMeta2},
|
||||
expected: []ObjMetadata{},
|
||||
},
|
||||
"Basic diff": {
|
||||
setA: []ObjMetadata{objMeta2, objMeta1},
|
||||
setB: []ObjMetadata{objMeta1},
|
||||
expected: []ObjMetadata{objMeta2},
|
||||
},
|
||||
"Subtract non-elements results in no change": {
|
||||
setA: []ObjMetadata{objMeta1},
|
||||
setB: []ObjMetadata{objMeta3, objMeta4},
|
||||
expected: []ObjMetadata{objMeta1},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual := SetDiff(tc.setA, tc.setB)
|
||||
if !SetEquals(tc.expected, actual) {
|
||||
t.Errorf("SetDiff expected set (%s), got (%s)", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnion(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
setA []ObjMetadata
|
||||
setB []ObjMetadata
|
||||
expected []ObjMetadata
|
||||
}{
|
||||
"Empty sets results in empty union": {
|
||||
setA: []ObjMetadata{},
|
||||
setB: []ObjMetadata{},
|
||||
expected: []ObjMetadata{},
|
||||
},
|
||||
"Empty second set results in same set": {
|
||||
setA: []ObjMetadata{objMeta1, objMeta3},
|
||||
setB: []ObjMetadata{},
|
||||
expected: []ObjMetadata{objMeta1, objMeta3},
|
||||
},
|
||||
"Empty initial set results in empty diff": {
|
||||
setA: []ObjMetadata{},
|
||||
setB: []ObjMetadata{objMeta1, objMeta3},
|
||||
expected: []ObjMetadata{objMeta1, objMeta3},
|
||||
},
|
||||
"Same sets in different order results in same set": {
|
||||
setA: []ObjMetadata{objMeta2, objMeta1},
|
||||
setB: []ObjMetadata{objMeta1, objMeta2},
|
||||
expected: []ObjMetadata{objMeta1, objMeta2},
|
||||
},
|
||||
"One item overlap": {
|
||||
setA: []ObjMetadata{objMeta2, objMeta1},
|
||||
setB: []ObjMetadata{objMeta1, objMeta3},
|
||||
expected: []ObjMetadata{objMeta1, objMeta2, objMeta3},
|
||||
},
|
||||
"Disjoint sets results in larger set": {
|
||||
setA: []ObjMetadata{objMeta1, objMeta2},
|
||||
setB: []ObjMetadata{objMeta3, objMeta4},
|
||||
expected: []ObjMetadata{objMeta1, objMeta2, objMeta3, objMeta4},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual := Union(tc.setA, tc.setB)
|
||||
if !SetEquals(tc.expected, actual) {
|
||||
t.Errorf("SetDiff expected set (%s), got (%s)", tc.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetEquals(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
setA []ObjMetadata
|
||||
setB []ObjMetadata
|
||||
isEqual bool
|
||||
}{
|
||||
"Empty sets results in empty union": {
|
||||
setA: []ObjMetadata{},
|
||||
setB: []ObjMetadata{},
|
||||
isEqual: true,
|
||||
},
|
||||
"Empty second set results in same set": {
|
||||
setA: []ObjMetadata{objMeta1, objMeta3},
|
||||
setB: []ObjMetadata{},
|
||||
isEqual: false,
|
||||
},
|
||||
"Empty initial set results in empty diff": {
|
||||
setA: []ObjMetadata{},
|
||||
setB: []ObjMetadata{objMeta1, objMeta3},
|
||||
isEqual: false,
|
||||
},
|
||||
"Different ordering are equal sets": {
|
||||
setA: []ObjMetadata{objMeta2, objMeta1},
|
||||
setB: []ObjMetadata{objMeta1, objMeta2},
|
||||
isEqual: true,
|
||||
},
|
||||
"One item overlap": {
|
||||
setA: []ObjMetadata{objMeta2, objMeta1},
|
||||
setB: []ObjMetadata{objMeta1, objMeta3},
|
||||
isEqual: false,
|
||||
},
|
||||
"Disjoint sets results in larger set": {
|
||||
setA: []ObjMetadata{objMeta1, objMeta2},
|
||||
setB: []ObjMetadata{objMeta3, objMeta4},
|
||||
isEqual: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
actual := SetEquals(tc.setA, tc.setB)
|
||||
if tc.isEqual != actual {
|
||||
t.Errorf("SetEqual expected (%t), got (%t)", tc.isEqual, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ func (i InventoryCustomType) ID() string {
|
|||
return id
|
||||
}
|
||||
|
||||
func (i InventoryCustomType) Load() ([]object.ObjMetadata, error) {
|
||||
var inv []object.ObjMetadata
|
||||
func (i InventoryCustomType) Load() (object.ObjMetadataSet, error) {
|
||||
var inv object.ObjMetadataSet
|
||||
s, found, err := unstructured.NestedSlice(i.inv.Object, "spec", "inventory")
|
||||
if err != nil {
|
||||
return inv, err
|
||||
|
|
@ -155,7 +155,7 @@ func (i InventoryCustomType) Load() ([]object.ObjMetadata, error) {
|
|||
return inv, nil
|
||||
}
|
||||
|
||||
func (i InventoryCustomType) Store(objs []object.ObjMetadata) error {
|
||||
func (i InventoryCustomType) Store(objs object.ObjMetadataSet) error {
|
||||
var inv []interface{}
|
||||
for _, obj := range objs {
|
||||
inv = append(inv, map[string]interface{}{
|
||||
|
|
|
|||
Loading…
Reference in New Issue