...

Source file src/sigs.k8s.io/cli-utils/test/e2e/namespace_filter_test.go

Documentation: sigs.k8s.io/cli-utils/test/e2e

     1  // Copyright 2020 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package e2e
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    13  	"sigs.k8s.io/cli-utils/pkg/apis/actuation"
    14  	"sigs.k8s.io/cli-utils/pkg/apply"
    15  	"sigs.k8s.io/cli-utils/pkg/apply/event"
    16  	"sigs.k8s.io/cli-utils/pkg/apply/filter"
    17  	"sigs.k8s.io/cli-utils/pkg/object"
    18  	"sigs.k8s.io/cli-utils/pkg/testutil"
    19  	"sigs.k8s.io/cli-utils/test/e2e/e2eutil"
    20  	"sigs.k8s.io/cli-utils/test/e2e/invconfig"
    21  	"sigs.k8s.io/controller-runtime/pkg/client"
    22  )
    23  
    24  //nolint:dupl // expEvents similar to other tests
    25  func namespaceFilterTest(ctx context.Context, c client.Client, invConfig invconfig.InventoryConfig, inventoryName, namespaceName string) {
    26  	By("apply resources in order based on depends-on annotation")
    27  	applier := invConfig.ApplierFactoryFunc()
    28  
    29  	inv := invConfig.InvWrapperFunc(invConfig.FactoryFunc(inventoryName, namespaceName, "test"))
    30  
    31  	namespace1Name := fmt.Sprintf("%s-ns1", namespaceName)
    32  
    33  	fields := struct{ Namespace string }{Namespace: namespace1Name}
    34  	namespace1Obj := e2eutil.TemplateToUnstructured(namespaceTemplate, fields)
    35  	podBObj := e2eutil.TemplateToUnstructured(podBTemplate, fields)
    36  
    37  	// Dependency order: podB -> namespace1
    38  	// Apply order: namespace1, podB
    39  	resources := []*unstructured.Unstructured{
    40  		namespace1Obj,
    41  		podBObj,
    42  	}
    43  
    44  	// Cleanup
    45  	defer func(ctx context.Context, c client.Client) {
    46  		e2eutil.DeleteUnstructuredIfExists(ctx, c, podBObj)
    47  		e2eutil.DeleteUnstructuredIfExists(ctx, c, namespace1Obj)
    48  	}(ctx, c)
    49  
    50  	applierEvents := e2eutil.RunCollect(applier.Run(ctx, inv, resources, apply.ApplierOptions{
    51  		EmitStatusEvents: false,
    52  	}))
    53  
    54  	expEvents := []testutil.ExpEvent{
    55  		{
    56  			// InitTask
    57  			EventType: event.InitType,
    58  			InitEvent: &testutil.ExpInitEvent{},
    59  		},
    60  		{
    61  			// InvAddTask start
    62  			EventType: event.ActionGroupType,
    63  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
    64  				Action:    event.InventoryAction,
    65  				GroupName: "inventory-add-0",
    66  				Type:      event.Started,
    67  			},
    68  		},
    69  		{
    70  			// InvAddTask finished
    71  			EventType: event.ActionGroupType,
    72  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
    73  				Action:    event.InventoryAction,
    74  				GroupName: "inventory-add-0",
    75  				Type:      event.Finished,
    76  			},
    77  		},
    78  		{
    79  			// ApplyTask start
    80  			EventType: event.ActionGroupType,
    81  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
    82  				Action:    event.ApplyAction,
    83  				GroupName: "apply-0",
    84  				Type:      event.Started,
    85  			},
    86  		},
    87  		{
    88  			// Apply namespace1 first
    89  			EventType: event.ApplyType,
    90  			ApplyEvent: &testutil.ExpApplyEvent{
    91  				GroupName:  "apply-0",
    92  				Status:     event.ApplySuccessful,
    93  				Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
    94  				Error:      nil,
    95  			},
    96  		},
    97  		{
    98  			// ApplyTask finished
    99  			EventType: event.ActionGroupType,
   100  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   101  				Action:    event.ApplyAction,
   102  				GroupName: "apply-0",
   103  				Type:      event.Finished,
   104  			},
   105  		},
   106  		{
   107  			// WaitTask start
   108  			EventType: event.ActionGroupType,
   109  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   110  				Action:    event.WaitAction,
   111  				GroupName: "wait-0",
   112  				Type:      event.Started,
   113  			},
   114  		},
   115  		{
   116  			// namespace1 reconcile Pending
   117  			EventType: event.WaitType,
   118  			WaitEvent: &testutil.ExpWaitEvent{
   119  				GroupName:  "wait-0",
   120  				Status:     event.ReconcilePending,
   121  				Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
   122  			},
   123  		},
   124  		{
   125  			// namespace1 confirmed Current.
   126  			EventType: event.WaitType,
   127  			WaitEvent: &testutil.ExpWaitEvent{
   128  				GroupName:  "wait-0",
   129  				Status:     event.ReconcileSuccessful,
   130  				Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
   131  			},
   132  		},
   133  		{
   134  			// WaitTask finished
   135  			EventType: event.ActionGroupType,
   136  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   137  				Action:    event.WaitAction,
   138  				GroupName: "wait-0",
   139  				Type:      event.Finished,
   140  			},
   141  		},
   142  		{
   143  			// ApplyTask start
   144  			EventType: event.ActionGroupType,
   145  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   146  				Action:    event.ApplyAction,
   147  				GroupName: "apply-1",
   148  				Type:      event.Started,
   149  			},
   150  		},
   151  		{
   152  			// Apply podB second
   153  			EventType: event.ApplyType,
   154  			ApplyEvent: &testutil.ExpApplyEvent{
   155  				GroupName:  "apply-1",
   156  				Status:     event.ApplySuccessful,
   157  				Identifier: object.UnstructuredToObjMetadata(podBObj),
   158  				Error:      nil,
   159  			},
   160  		},
   161  		{
   162  			// ApplyTask finished
   163  			EventType: event.ActionGroupType,
   164  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   165  				Action:    event.ApplyAction,
   166  				GroupName: "apply-1",
   167  				Type:      event.Finished,
   168  			},
   169  		},
   170  		{
   171  			// WaitTask start
   172  			EventType: event.ActionGroupType,
   173  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   174  				Action:    event.WaitAction,
   175  				GroupName: "wait-1",
   176  				Type:      event.Started,
   177  			},
   178  		},
   179  		{
   180  			// podB reconcile Pending.
   181  			EventType: event.WaitType,
   182  			WaitEvent: &testutil.ExpWaitEvent{
   183  				GroupName:  "wait-1",
   184  				Status:     event.ReconcilePending,
   185  				Identifier: object.UnstructuredToObjMetadata(podBObj),
   186  			},
   187  		},
   188  		{
   189  			// podB confirmed Current.
   190  			EventType: event.WaitType,
   191  			WaitEvent: &testutil.ExpWaitEvent{
   192  				GroupName:  "wait-1",
   193  				Status:     event.ReconcileSuccessful,
   194  				Identifier: object.UnstructuredToObjMetadata(podBObj),
   195  			},
   196  		},
   197  		{
   198  			// WaitTask finished
   199  			EventType: event.ActionGroupType,
   200  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   201  				Action:    event.WaitAction,
   202  				GroupName: "wait-1",
   203  				Type:      event.Finished,
   204  			},
   205  		},
   206  		{
   207  			// InvSetTask start
   208  			EventType: event.ActionGroupType,
   209  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   210  				Action:    event.InventoryAction,
   211  				GroupName: "inventory-set-0",
   212  				Type:      event.Started,
   213  			},
   214  		},
   215  		{
   216  			// InvSetTask finished
   217  			EventType: event.ActionGroupType,
   218  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   219  				Action:    event.InventoryAction,
   220  				GroupName: "inventory-set-0",
   221  				Type:      event.Finished,
   222  			},
   223  		},
   224  	}
   225  	receivedEvents := testutil.EventsToExpEvents(applierEvents)
   226  
   227  	expEvents, receivedEvents = e2eutil.FilterOptionalEvents(expEvents, receivedEvents)
   228  
   229  	Expect(receivedEvents).To(testutil.Equal(expEvents))
   230  
   231  	By("verify namespace1 created")
   232  	e2eutil.AssertUnstructuredExists(ctx, c, namespace1Obj)
   233  
   234  	By("verify podB created and ready")
   235  	result := e2eutil.AssertUnstructuredExists(ctx, c, podBObj)
   236  	podIP, found, err := object.NestedField(result.Object, "status", "podIP")
   237  	Expect(err).NotTo(HaveOccurred())
   238  	Expect(found).To(BeTrue())
   239  	Expect(podIP).NotTo(BeEmpty()) // use podIP as proxy for readiness
   240  
   241  	// Attempt to Prune namespace
   242  	resources = []*unstructured.Unstructured{
   243  		podBObj,
   244  	}
   245  
   246  	applierEvents = e2eutil.RunCollect(applier.Run(ctx, inv, resources, apply.ApplierOptions{
   247  		EmitStatusEvents: false,
   248  	}))
   249  
   250  	expEvents = []testutil.ExpEvent{
   251  		{
   252  			// InitTask
   253  			EventType: event.InitType,
   254  			InitEvent: &testutil.ExpInitEvent{},
   255  		},
   256  		{
   257  			// InvAddTask start
   258  			EventType: event.ActionGroupType,
   259  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   260  				Action:    event.InventoryAction,
   261  				GroupName: "inventory-add-0",
   262  				Type:      event.Started,
   263  			},
   264  		},
   265  		{
   266  			// InvAddTask finished
   267  			EventType: event.ActionGroupType,
   268  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   269  				Action:    event.InventoryAction,
   270  				GroupName: "inventory-add-0",
   271  				Type:      event.Finished,
   272  			},
   273  		},
   274  		{
   275  			// ApplyTask start
   276  			EventType: event.ActionGroupType,
   277  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   278  				Action:    event.ApplyAction,
   279  				GroupName: "apply-0",
   280  				Type:      event.Started,
   281  			},
   282  		},
   283  		{
   284  			// Apply podB Skipped (because depends on namespace being deleted)
   285  			EventType: event.ApplyType,
   286  			ApplyEvent: &testutil.ExpApplyEvent{
   287  				GroupName:  "apply-0",
   288  				Status:     event.ApplySkipped,
   289  				Identifier: object.UnstructuredToObjMetadata(podBObj),
   290  				Error: testutil.EqualError(&filter.DependencyActuationMismatchError{
   291  					Object:           object.UnstructuredToObjMetadata(podBObj),
   292  					Strategy:         actuation.ActuationStrategyApply,
   293  					Relationship:     filter.RelationshipDependency,
   294  					Relation:         object.UnstructuredToObjMetadata(namespace1Obj),
   295  					RelationStrategy: actuation.ActuationStrategyDelete,
   296  				}),
   297  			},
   298  		},
   299  		{
   300  			// ApplyTask finished
   301  			EventType: event.ActionGroupType,
   302  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   303  				Action:    event.ApplyAction,
   304  				GroupName: "apply-0",
   305  				Type:      event.Finished,
   306  			},
   307  		},
   308  		{
   309  			// WaitTask start
   310  			EventType: event.ActionGroupType,
   311  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   312  				Action:    event.WaitAction,
   313  				GroupName: "wait-0",
   314  				Type:      event.Started,
   315  			},
   316  		},
   317  		{
   318  			// podB Reconcile Skipped (because apply skipped)
   319  			EventType: event.WaitType,
   320  			WaitEvent: &testutil.ExpWaitEvent{
   321  				GroupName:  "wait-0",
   322  				Status:     event.ReconcileSkipped,
   323  				Identifier: object.UnstructuredToObjMetadata(podBObj),
   324  			},
   325  		},
   326  		{
   327  			// WaitTask finished
   328  			EventType: event.ActionGroupType,
   329  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   330  				Action:    event.WaitAction,
   331  				GroupName: "wait-0",
   332  				Type:      event.Finished,
   333  			},
   334  		},
   335  		{
   336  			// PruneTask start
   337  			EventType: event.ActionGroupType,
   338  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   339  				Action:    event.PruneAction,
   340  				GroupName: "prune-0",
   341  				Type:      event.Started,
   342  			},
   343  		},
   344  		{
   345  			// Prune namespace1 Skipped (because namespace still in use)
   346  			EventType: event.PruneType,
   347  			PruneEvent: &testutil.ExpPruneEvent{
   348  				GroupName:  "prune-0",
   349  				Status:     event.PruneSkipped,
   350  				Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
   351  				Error: testutil.EqualError(&filter.NamespaceInUseError{
   352  					Namespace: namespace1Name,
   353  				}),
   354  			},
   355  		},
   356  		{
   357  			// PruneTask finished
   358  			EventType: event.ActionGroupType,
   359  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   360  				Action:    event.PruneAction,
   361  				GroupName: "prune-0",
   362  				Type:      event.Finished,
   363  			},
   364  		},
   365  		{
   366  			// WaitTask start
   367  			EventType: event.ActionGroupType,
   368  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   369  				Action:    event.WaitAction,
   370  				GroupName: "wait-1",
   371  				Type:      event.Started,
   372  			},
   373  		},
   374  		{
   375  			// namespace1 reconcile Skipped (because prune skipped).
   376  			EventType: event.WaitType,
   377  			WaitEvent: &testutil.ExpWaitEvent{
   378  				GroupName:  "wait-1",
   379  				Status:     event.ReconcileSkipped,
   380  				Identifier: object.UnstructuredToObjMetadata(namespace1Obj),
   381  			},
   382  		},
   383  		{
   384  			// WaitTask finished
   385  			EventType: event.ActionGroupType,
   386  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   387  				Action:    event.WaitAction,
   388  				GroupName: "wait-1",
   389  				Type:      event.Finished,
   390  			},
   391  		},
   392  		{
   393  			// InvSetTask start
   394  			EventType: event.ActionGroupType,
   395  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   396  				Action:    event.InventoryAction,
   397  				GroupName: "inventory-set-0",
   398  				Type:      event.Started,
   399  			},
   400  		},
   401  		{
   402  			// InvSetTask finished
   403  			EventType: event.ActionGroupType,
   404  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   405  				Action:    event.InventoryAction,
   406  				GroupName: "inventory-set-0",
   407  				Type:      event.Finished,
   408  			},
   409  		},
   410  	}
   411  	Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
   412  
   413  	By("verify namespace1 not deleted")
   414  	result = e2eutil.AssertUnstructuredExists(ctx, c, namespace1Obj)
   415  	ts, found, err := object.NestedField(result.Object, "metadata", "deletionTimestamp")
   416  	Expect(err).NotTo(HaveOccurred())
   417  	Expect(found).To(BeFalse(), "deletionTimestamp found: ", ts)
   418  
   419  	By("verify podB not deleted")
   420  	result = e2eutil.AssertUnstructuredExists(ctx, c, podBObj)
   421  	ts, found, err = object.NestedField(result.Object, "metadata", "deletionTimestamp")
   422  	Expect(err).NotTo(HaveOccurred())
   423  	Expect(found).To(BeFalse(), "deletionTimestamp found: ", ts)
   424  }
   425  

View as plain text