...

Source file src/sigs.k8s.io/cli-utils/test/e2e/crd_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  	"strings"
     9  	"time"
    10  
    11  	. "github.com/onsi/ginkgo/v2"
    12  	. "github.com/onsi/gomega"
    13  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    14  	"sigs.k8s.io/cli-utils/pkg/apply"
    15  	"sigs.k8s.io/cli-utils/pkg/apply/event"
    16  	"sigs.k8s.io/cli-utils/pkg/inventory"
    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 mutation tests
    25  func crdTest(ctx context.Context, _ client.Client, invConfig invconfig.InventoryConfig, inventoryName, namespaceName string) {
    26  	By("apply a set of resources that includes both a crd and a cr")
    27  	applier := invConfig.ApplierFactoryFunc()
    28  
    29  	inv := invConfig.InvWrapperFunc(invConfig.FactoryFunc(inventoryName, namespaceName, "test"))
    30  
    31  	crdObj := e2eutil.ManifestToUnstructured(crd)
    32  	crObj := e2eutil.ManifestToUnstructured(cr)
    33  
    34  	resources := []*unstructured.Unstructured{
    35  		crObj,
    36  		crdObj,
    37  	}
    38  
    39  	applierEvents := e2eutil.RunCollect(applier.Run(ctx, inv, resources, apply.ApplierOptions{
    40  		ReconcileTimeout: 2 * time.Minute,
    41  		EmitStatusEvents: false,
    42  	}))
    43  
    44  	expEvents := []testutil.ExpEvent{
    45  		{
    46  			// InitTask
    47  			EventType: event.InitType,
    48  			InitEvent: &testutil.ExpInitEvent{},
    49  		},
    50  		{
    51  			// InvAddTask start
    52  			EventType: event.ActionGroupType,
    53  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
    54  				Action:    event.InventoryAction,
    55  				GroupName: "inventory-add-0",
    56  				Type:      event.Started,
    57  			},
    58  		},
    59  		{
    60  			// InvAddTask finished
    61  			EventType: event.ActionGroupType,
    62  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
    63  				Action:    event.InventoryAction,
    64  				GroupName: "inventory-add-0",
    65  				Type:      event.Finished,
    66  			},
    67  		},
    68  		{
    69  			// ApplyTask start
    70  			EventType: event.ActionGroupType,
    71  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
    72  				Action:    event.ApplyAction,
    73  				GroupName: "apply-0",
    74  				Type:      event.Started,
    75  			},
    76  		},
    77  		{
    78  			// Apply CRD before custom resource
    79  			EventType: event.ApplyType,
    80  			ApplyEvent: &testutil.ExpApplyEvent{
    81  				GroupName:  "apply-0",
    82  				Status:     event.ApplySuccessful,
    83  				Identifier: object.UnstructuredToObjMetadata(crdObj),
    84  				Error:      nil,
    85  			},
    86  		},
    87  		{
    88  			// ApplyTask finished
    89  			EventType: event.ActionGroupType,
    90  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
    91  				Action:    event.ApplyAction,
    92  				GroupName: "apply-0",
    93  				Type:      event.Finished,
    94  			},
    95  		},
    96  		{
    97  			// WaitTask start
    98  			EventType: event.ActionGroupType,
    99  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   100  				Action:    event.WaitAction,
   101  				GroupName: "wait-0",
   102  				Type:      event.Started,
   103  			},
   104  		},
   105  		{
   106  			// CRD reconcile Pending
   107  			EventType: event.WaitType,
   108  			WaitEvent: &testutil.ExpWaitEvent{
   109  				GroupName:  "wait-0",
   110  				Status:     event.ReconcilePending,
   111  				Identifier: object.UnstructuredToObjMetadata(crdObj),
   112  			},
   113  		},
   114  		{
   115  			// CRD confirmed Current.
   116  			EventType: event.WaitType,
   117  			WaitEvent: &testutil.ExpWaitEvent{
   118  				GroupName:  "wait-0",
   119  				Status:     event.ReconcileSuccessful,
   120  				Identifier: object.UnstructuredToObjMetadata(crdObj),
   121  			},
   122  		},
   123  		{
   124  			// WaitTask finished
   125  			EventType: event.ActionGroupType,
   126  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   127  				Action:    event.WaitAction,
   128  				GroupName: "wait-0",
   129  				Type:      event.Finished,
   130  			},
   131  		},
   132  		{
   133  			// ApplyTask start
   134  			EventType: event.ActionGroupType,
   135  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   136  				Action:    event.ApplyAction,
   137  				GroupName: "apply-1",
   138  				Type:      event.Started,
   139  			},
   140  		},
   141  		{
   142  			// Apply CRD before custom resource
   143  			EventType: event.ApplyType,
   144  			ApplyEvent: &testutil.ExpApplyEvent{
   145  				GroupName:  "apply-1",
   146  				Status:     event.ApplySuccessful,
   147  				Identifier: object.UnstructuredToObjMetadata(crObj),
   148  				Error:      nil,
   149  			},
   150  		},
   151  		{
   152  			// ApplyTask finished
   153  			EventType: event.ActionGroupType,
   154  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   155  				Action:    event.ApplyAction,
   156  				GroupName: "apply-1",
   157  				Type:      event.Finished,
   158  			},
   159  		},
   160  		{
   161  			// WaitTask start
   162  			EventType: event.ActionGroupType,
   163  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   164  				Action:    event.WaitAction,
   165  				GroupName: "wait-1",
   166  				Type:      event.Started,
   167  			},
   168  		},
   169  		{
   170  			// CR reconcile Pending
   171  			EventType: event.WaitType,
   172  			WaitEvent: &testutil.ExpWaitEvent{
   173  				GroupName:  "wait-1",
   174  				Status:     event.ReconcilePending,
   175  				Identifier: object.UnstructuredToObjMetadata(crObj),
   176  			},
   177  		},
   178  		{
   179  			// CR confirmed Current.
   180  			EventType: event.WaitType,
   181  			WaitEvent: &testutil.ExpWaitEvent{
   182  				GroupName:  "wait-1",
   183  				Status:     event.ReconcileSuccessful,
   184  				Identifier: object.UnstructuredToObjMetadata(crObj),
   185  			},
   186  		},
   187  		{
   188  			// WaitTask finished
   189  			EventType: event.ActionGroupType,
   190  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   191  				Action:    event.WaitAction,
   192  				GroupName: "wait-1",
   193  				Type:      event.Finished,
   194  			},
   195  		},
   196  		{
   197  			// InvSetTask start
   198  			EventType: event.ActionGroupType,
   199  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   200  				Action:    event.InventoryAction,
   201  				GroupName: "inventory-set-0",
   202  				Type:      event.Started,
   203  			},
   204  		},
   205  		{
   206  			// InvSetTask finished
   207  			EventType: event.ActionGroupType,
   208  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   209  				Action:    event.InventoryAction,
   210  				GroupName: "inventory-set-0",
   211  				Type:      event.Finished,
   212  			},
   213  		},
   214  	}
   215  	receivedEvents := testutil.EventsToExpEvents(applierEvents)
   216  
   217  	expEvents, receivedEvents = e2eutil.FilterOptionalEvents(expEvents, receivedEvents)
   218  
   219  	Expect(receivedEvents).To(testutil.Equal(expEvents))
   220  
   221  	By("destroy the resources, including the crd")
   222  	destroyer := invConfig.DestroyerFactoryFunc()
   223  	options := apply.DestroyerOptions{InventoryPolicy: inventory.PolicyAdoptIfNoInventory}
   224  	destroyerEvents := e2eutil.RunCollect(destroyer.Run(ctx, inv, options))
   225  
   226  	expEvents = []testutil.ExpEvent{
   227  		{
   228  			// InitTask
   229  			EventType: event.InitType,
   230  			InitEvent: &testutil.ExpInitEvent{},
   231  		},
   232  		{
   233  			// PruneTask start
   234  			EventType: event.ActionGroupType,
   235  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   236  				Action:    event.DeleteAction,
   237  				GroupName: "prune-0",
   238  				Type:      event.Started,
   239  			},
   240  		},
   241  		{
   242  			// Delete custom resource first
   243  			EventType: event.DeleteType,
   244  			DeleteEvent: &testutil.ExpDeleteEvent{
   245  				GroupName:  "prune-0",
   246  				Status:     event.DeleteSuccessful,
   247  				Identifier: object.UnstructuredToObjMetadata(crObj),
   248  				Error:      nil,
   249  			},
   250  		},
   251  		{
   252  			// PruneTask finished
   253  			EventType: event.ActionGroupType,
   254  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   255  				Action:    event.DeleteAction,
   256  				GroupName: "prune-0",
   257  				Type:      event.Finished,
   258  			},
   259  		},
   260  		{
   261  			// WaitTask start
   262  			EventType: event.ActionGroupType,
   263  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   264  				Action:    event.WaitAction,
   265  				GroupName: "wait-0",
   266  				Type:      event.Started,
   267  			},
   268  		},
   269  		{
   270  			// CR reconcile Pending
   271  			EventType: event.WaitType,
   272  			WaitEvent: &testutil.ExpWaitEvent{
   273  				GroupName:  "wait-0",
   274  				Status:     event.ReconcilePending,
   275  				Identifier: object.UnstructuredToObjMetadata(crObj),
   276  			},
   277  		},
   278  		{
   279  			// CR confirmed NotFound.
   280  			EventType: event.WaitType,
   281  			WaitEvent: &testutil.ExpWaitEvent{
   282  				GroupName:  "wait-0",
   283  				Status:     event.ReconcileSuccessful,
   284  				Identifier: object.UnstructuredToObjMetadata(crObj),
   285  			},
   286  		},
   287  		{
   288  			// WaitTask finished
   289  			EventType: event.ActionGroupType,
   290  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   291  				Action:    event.WaitAction,
   292  				GroupName: "wait-0",
   293  				Type:      event.Finished,
   294  			},
   295  		},
   296  		{
   297  			// PruneTask start
   298  			EventType: event.ActionGroupType,
   299  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   300  				Action:    event.DeleteAction,
   301  				GroupName: "prune-1",
   302  				Type:      event.Started,
   303  			},
   304  		},
   305  		{
   306  			// Delete CRD after custom resource
   307  			EventType: event.DeleteType,
   308  			DeleteEvent: &testutil.ExpDeleteEvent{
   309  				GroupName:  "prune-1",
   310  				Status:     event.DeleteSuccessful,
   311  				Identifier: object.UnstructuredToObjMetadata(crdObj),
   312  				Error:      nil,
   313  			},
   314  		},
   315  		{
   316  			// PruneTask finished
   317  			EventType: event.ActionGroupType,
   318  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   319  				Action:    event.DeleteAction,
   320  				GroupName: "prune-1",
   321  				Type:      event.Finished,
   322  			},
   323  		},
   324  		{
   325  			// WaitTask start
   326  			EventType: event.ActionGroupType,
   327  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   328  				Action:    event.WaitAction,
   329  				GroupName: "wait-1",
   330  				Type:      event.Started,
   331  			},
   332  		},
   333  		{
   334  			// CRD reconcile Pending.
   335  			EventType: event.WaitType,
   336  			WaitEvent: &testutil.ExpWaitEvent{
   337  				GroupName:  "wait-1",
   338  				Status:     event.ReconcilePending,
   339  				Identifier: object.UnstructuredToObjMetadata(crdObj),
   340  			},
   341  		},
   342  		{
   343  			// CRD confirmed NotFound.
   344  			EventType: event.WaitType,
   345  			WaitEvent: &testutil.ExpWaitEvent{
   346  				GroupName:  "wait-1",
   347  				Status:     event.ReconcileSuccessful,
   348  				Identifier: object.UnstructuredToObjMetadata(crdObj),
   349  			},
   350  		},
   351  		{
   352  			// WaitTask finished
   353  			EventType: event.ActionGroupType,
   354  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   355  				Action:    event.WaitAction,
   356  				GroupName: "wait-1",
   357  				Type:      event.Finished,
   358  			},
   359  		},
   360  		{
   361  			// DeleteInvTask start
   362  			EventType: event.ActionGroupType,
   363  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   364  				Action:    event.InventoryAction,
   365  				GroupName: "delete-inventory-0",
   366  				Type:      event.Started,
   367  			},
   368  		},
   369  		{
   370  			// DeleteInvTask finished
   371  			EventType: event.ActionGroupType,
   372  			ActionGroupEvent: &testutil.ExpActionGroupEvent{
   373  				Action:    event.InventoryAction,
   374  				GroupName: "delete-inventory-0",
   375  				Type:      event.Finished,
   376  			},
   377  		},
   378  	}
   379  	receivedEvents = testutil.EventsToExpEvents(destroyerEvents)
   380  
   381  	expEvents, receivedEvents = e2eutil.FilterOptionalEvents(expEvents, receivedEvents)
   382  
   383  	Expect(receivedEvents).To(testutil.Equal(expEvents))
   384  }
   385  
   386  var crd = []byte(strings.TrimSpace(`
   387  apiVersion: apiextensions.k8s.io/v1
   388  kind: CustomResourceDefinition
   389  metadata:
   390    name: examples.cli-utils.example.io
   391  spec:
   392    conversion:
   393      strategy: None
   394    group: cli-utils.example.io
   395    names:
   396      kind: Example
   397      listKind: ExampleList
   398      plural: examples
   399      singular: example
   400    scope: Cluster
   401    versions:
   402    - name: v1alpha1
   403      schema:
   404        openAPIV3Schema:
   405          description: Example for cli-utils e2e tests
   406          properties:
   407            apiVersion:
   408              type: string
   409            kind:
   410              type: string
   411            metadata:
   412              type: object
   413            spec:
   414              description: Example for cli-utils e2e tests
   415              properties:
   416                replicas:
   417                  description: Number of replicas 
   418                  type: integer
   419              required:
   420              - replicas
   421              type: object
   422          type: object
   423      served: true
   424      storage: true
   425      subresources: {}
   426  `))
   427  
   428  var cr = []byte(strings.TrimSpace(`
   429  apiVersion: cli-utils.example.io/v1alpha1
   430  kind: Example
   431  metadata:
   432    name: example-cr
   433  spec:
   434    replicas: 4
   435  `))
   436  

View as plain text