...

Source file src/edge-infra.dev/pkg/f8n/warehouse/k8s/controllers/lumperctl/integration/unpacked_pallet_controller_test.go

Documentation: edge-infra.dev/pkg/f8n/warehouse/k8s/controllers/lumperctl/integration

     1  package integration
     2  
     3  import (
     4  	_ "embed"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/davecgh/go-spew/spew"
     9  	"gotest.tools/v3/assert"
    10  	"gotest.tools/v3/assert/cmp"
    11  	"gotest.tools/v3/poll"
    12  	appsv1 "k8s.io/api/apps/v1"
    13  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    14  	"k8s.io/apimachinery/pkg/types"
    15  	"sigs.k8s.io/controller-runtime/pkg/client"
    16  	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    17  
    18  	whv1 "edge-infra.dev/pkg/f8n/warehouse/k8s/apis/v1alpha2"
    19  	"edge-infra.dev/pkg/f8n/warehouse/oci/layer"
    20  	"edge-infra.dev/pkg/k8s/meta/status"
    21  	"edge-infra.dev/pkg/k8s/runtime/conditions"
    22  	"edge-infra.dev/pkg/k8s/testing/kmp"
    23  	"edge-infra.dev/pkg/k8s/unstructured"
    24  	"edge-infra.dev/test/f2"
    25  	"edge-infra.dev/test/f2/x/ktest"
    26  )
    27  
    28  func TestUnpackedPalletController_Inventory(t *testing.T) {
    29  	var (
    30  		id string
    31  		v1 testPallet
    32  		v2 testPallet
    33  		u  = &whv1.UnpackedPallet{}
    34  	)
    35  
    36  	inv := f2.NewFeature("Inventories reconciled objects").
    37  		Setup("Create and push test packages", func(ctx f2.Context, t *testing.T) f2.Context {
    38  			id = fmt.Sprintf("inv-%s", ctx.RunID)
    39  			v1 = createAndPushPallet(ctx, t, id, "v1", createLayer(t, layer.Runtime, minimalv1))
    40  			v2 = createAndPushPallet(ctx, t, id, "v2", createLayer(t, layer.Runtime, minimalv2))
    41  			return ctx
    42  		}).
    43  		Test("Creates inventory", func(ctx f2.Context, t *testing.T) f2.Context {
    44  			var (
    45  				u = unpackedPallet(ctx, t, v1.name, v1.pallet, whv1.WithPrune())
    46  				k = ktest.FromContextT(ctx, t)
    47  			)
    48  
    49  			assert.NilError(t, k.Client.Create(ctx, u))
    50  			k.WaitOn(t, k.Check(u, kmp.HasInventory(v1.inv)))
    51  			k.WaitOn(t, k.InventoryExists(v1.inv))
    52  
    53  			return ctx
    54  		}).
    55  		Test("Handles inventory changes", func(ctx f2.Context, t *testing.T) f2.Context {
    56  			k := ktest.FromContextT(ctx, t)
    57  
    58  			assert.NilError(t, k.Client.Get(
    59  				ctx, types.NamespacedName{Name: v1.name, Namespace: k.Namespace}, u,
    60  			))
    61  
    62  			patch := client.MergeFrom(u.DeepCopy())
    63  			u.Spec.Digest = v2.digest
    64  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
    65  
    66  			k.WaitOn(t, k.Check(u, kmp.HasInventory(v2.inv)))
    67  			k.WaitOn(t, k.InventoryExists(v2.inv))
    68  			k.WaitOn(t, k.InventoryPruned(v2.inv, v1.inv))
    69  			assert.Equal(t, u.Status.ObservedGeneration, int64(2),
    70  				"inventory was updated without updating status.observedGeneration")
    71  
    72  			return ctx
    73  		}).
    74  		Test("With pruning disabled", func(ctx f2.Context, t *testing.T) f2.Context {
    75  			k := ktest.FromContextT(ctx, t)
    76  
    77  			// Disable pruning on object already syncing v2, and configure it to sync v1
    78  			// instead
    79  			assert.NilError(t, k.Client.Get(
    80  				ctx, types.NamespacedName{Name: v1.name, Namespace: k.Namespace}, u,
    81  			))
    82  
    83  			patch := client.MergeFrom(u.DeepCopy())
    84  			u.Spec.Prune = false
    85  			u.Spec.Digest = v1.digest
    86  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
    87  
    88  			// Wait for re-reconciliation to complete to v1 digest, verify that
    89  			// inv matches v1 and those objects were actually applied
    90  			k.WaitOn(t, k.Check(u, kmp.HasInventory(v1.inv)))
    91  			k.WaitOn(t, k.InventoryExists(v1.inv))
    92  			// Ensure that we have finished reconciling, which means pruning should
    93  			// have happened
    94  			k.WaitOn(t, k.Check(u, unpackedPalletReady))
    95  			// Ensure nothing was deleted
    96  			diff, err := v2.inv.Diff(v1.inv)
    97  			assert.NilError(t, err)
    98  			k.WaitOn(t, k.ObjsExist(unstructured.ToClientObjArray(diff...)))
    99  
   100  			return ctx
   101  		}).
   102  		Feature()
   103  
   104  	f.Test(t, inv)
   105  }
   106  
   107  func TestUnpackedPalletController_Status(t *testing.T) {
   108  	var (
   109  		id string
   110  		v1 testPallet
   111  		u  *whv1.UnpackedPallet
   112  	)
   113  
   114  	status := f2.NewFeature("Reconciles its Status").
   115  		Setup("Create and push test packages", func(ctx f2.Context, t *testing.T) f2.Context {
   116  			id = fmt.Sprintf("status-%s", ctx.RunID)
   117  			v1 = createAndPushPallet(ctx, t, id, "v1",
   118  				createLayer(t, layer.Runtime, minimalv1),
   119  				fakeInfraLayer(t),
   120  				fakeL5dLayer(t),
   121  			)
   122  			u = unpackedPallet(ctx, t, v1.name, v1.pallet,
   123  				whv1.WithInfra(),
   124  				whv1.WithCapabilities(string(l5dCap)),
   125  				whv1.WithPrune(),
   126  			)
   127  
   128  			k := ktest.FromContextT(ctx, t)
   129  
   130  			assert.NilError(t, k.Client.Create(ctx, u))
   131  			k.WaitOn(t, k.Check(u, unpackedPalletReady))
   132  
   133  			return ctx
   134  		}).
   135  		Test("Package digest is persisted on status", func(ctx f2.Context, t *testing.T) f2.Context {
   136  			assert.Equal(t, v1.digest, u.Status.LastAttempted)
   137  			assert.Equal(t, int64(1), u.Status.ObservedGeneration)
   138  			return ctx
   139  		}).
   140  		Test("Updates Conditions Based on Layers", func(ctx f2.Context, t *testing.T) f2.Context {
   141  			var (
   142  				k = ktest.FromContextT(ctx, t)
   143  
   144  				healthy      = conditions.TrueCondition(whv1.HealthyCondition, status.SucceededReason, "Objects reconciled")
   145  				fetched      = conditions.TrueCondition(whv1.FetchedArtifactCondition, whv1.FetchSucceededReason, "Successfully retrieved artifact")
   146  				runtimeReady = conditions.TrueCondition(whv1.RuntimeReadyCondition, status.SucceededReason, "Objects reconciled")
   147  				runCapsReady = conditions.TrueCondition(whv1.RuntimeCapabilitiesReadyCondition, status.SucceededReason, "Objects reconciled")
   148  				infraReady   = conditions.TrueCondition(whv1.InfraReadyCondition, status.SucceededReason, "Objects reconciled")
   149  				ready        = conditions.TrueCondition(status.ReadyCondition, status.SucceededReason, "Objects reconciled")
   150  				reconciling  = conditions.TrueCondition(status.ReconcilingCondition, status.ProgressingWithRetryReason, "")
   151  				notReady     = conditions.FalseCondition(status.ReadyCondition, whv1.FetchFailedReason, "404")
   152  				fetchFail    = conditions.FalseCondition(whv1.FetchedArtifactCondition, whv1.FetchFailedReason, "404")
   153  			)
   154  
   155  			// Should initially have all 3 specialized Ready conditions + overall
   156  			// healthy condition
   157  			k.WaitOn(t, k.Check(u, kmp.HasEqualConditions([]metav1.Condition{
   158  				*ready,
   159  				*fetched,
   160  				*healthy,
   161  				*infraReady,
   162  				*runCapsReady,
   163  				*runtimeReady,
   164  			})))
   165  
   166  			// Remove InfraReady when its not appropriate
   167  			patch := client.MergeFrom(u.DeepCopy())
   168  			u.Spec.UnpackOptions.Infra = false
   169  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   170  			k.WaitOn(t, k.Check(u, kmp.HasEqualConditions([]metav1.Condition{
   171  				*ready,
   172  				*fetched,
   173  				*healthy,
   174  				*runCapsReady,
   175  				*runtimeReady,
   176  			})))
   177  
   178  			// Remove RuntimeCapabilityReady when its not appropriate
   179  			patch = client.MergeFrom(u.DeepCopy())
   180  			u.Spec.UnpackOptions.Capabilities = []string{}
   181  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   182  			k.WaitOn(t, k.Check(u, kmp.HasEqualConditions([]metav1.Condition{
   183  				*ready,
   184  				*fetched,
   185  				*healthy,
   186  				*runtimeReady,
   187  			})))
   188  
   189  			// Infra only should still end up with a healthy / Ready pallet
   190  			patch = client.MergeFrom(u.DeepCopy())
   191  			u.Spec.UnpackOptions.Runtime = false
   192  			u.Spec.UnpackOptions.Infra = true
   193  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   194  			k.WaitOn(t, k.Check(u, kmp.HasEqualConditions([]metav1.Condition{
   195  				*ready,
   196  				*fetched,
   197  				*healthy,
   198  				*infraReady,
   199  			})))
   200  
   201  			// Updating to a missing tag or digest causes Fetch to fail
   202  			oldTag := u.Spec.Tag
   203  			oldDigest := u.Spec.Digest
   204  			patch = client.MergeFrom(u.DeepCopy())
   205  			u.Spec.Digest = ""
   206  			u.Spec.Tag = "not-found"
   207  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   208  			k.WaitOn(t, k.Check(u, kmp.HasEqualConditions([]metav1.Condition{
   209  				*reconciling,
   210  				*notReady,
   211  				*fetchFail,
   212  				*healthy,
   213  				*infraReady,
   214  			})))
   215  
   216  			// Reverting to a correct tag should reconcile and update conditions
   217  			patch = client.MergeFrom(u.DeepCopy())
   218  			u.Spec.Digest = oldDigest
   219  			u.Spec.Tag = oldTag
   220  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   221  			k.WaitOn(t, k.Check(u, kmp.HasEqualConditions([]metav1.Condition{
   222  				*ready,
   223  				*fetched,
   224  				*healthy,
   225  				*infraReady,
   226  			})))
   227  
   228  			return ctx
   229  		}).
   230  		Feature()
   231  
   232  	f.Test(t, status)
   233  }
   234  
   235  func TestUnpackedPalletController_Finalizer(t *testing.T) {
   236  	var (
   237  		p testPallet
   238  		u = &whv1.UnpackedPallet{}
   239  	)
   240  
   241  	finalizer := f2.NewFeature("Finalizers").
   242  		Setup("Setup UnpackedPallet", func(ctx f2.Context, t *testing.T) f2.Context {
   243  			k := ktest.FromContextT(ctx, t)
   244  
   245  			p = createAndPushPallet(ctx, t, fmt.Sprintf("fin-%s", ctx.RunID), "v1",
   246  				createLayer(t, layer.Runtime, minimalv1))
   247  			u = unpackedPallet(ctx, t, p.name, p.pallet, whv1.WithPrune())
   248  
   249  			assert.NilError(t, k.Client.Create(ctx, u))
   250  			// Make sure that objects actually exist before testing finalizer behavior
   251  			k.WaitOn(t, k.Check(u, kmp.HasInventory(p.inv)))
   252  			k.WaitOn(t, k.InventoryExists(p.inv))
   253  
   254  			return ctx
   255  		}).
   256  		Test("Finalizer is added", func(ctx f2.Context, t *testing.T) f2.Context {
   257  			if !controllerutil.ContainsFinalizer(u, whv1.WarehouseFinalizer) {
   258  				t.Error("finalizer not added to unpackedpallet", spew.Sprintln(u))
   259  			}
   260  
   261  			return ctx
   262  		}).
   263  		Test("Garbage is collected on delete", func(ctx f2.Context, t *testing.T) f2.Context {
   264  			k := ktest.FromContextT(ctx, t)
   265  
   266  			assert.NilError(t, k.Client.Delete(ctx, u))
   267  			// Object being deleted means that finalizer was successfully removed.
   268  			k.WaitOn(t, k.ObjDeleted(u))
   269  
   270  			objs, err := p.inv.ListObjects()
   271  			assert.NilError(t, err)
   272  			k.WaitOn(t, k.ObjsDeleted(unstructured.ToClientObjArray(objs...)))
   273  
   274  			return ctx
   275  		}).
   276  		Test("Honors spec.prune", func(ctx f2.Context, t *testing.T) f2.Context {
   277  			var (
   278  				k  = ktest.FromContextT(ctx, t)
   279  				id = fmt.Sprintf("fin-prune-%s", ctx.RunID)
   280  				v1 = createAndPushPallet(ctx, t, id, "v1", createLayer(t, layer.Runtime, minimalv1))
   281  				u  = unpackedPallet(ctx, t, v1.name, v1.pallet)
   282  			)
   283  
   284  			assert.NilError(t, k.Client.Create(ctx, u))
   285  			k.WaitOn(t, k.Check(u, kmp.HasInventory(v1.inv)))
   286  			k.WaitOn(t, k.InventoryExists(v1.inv))
   287  			assert.NilError(t, k.Client.Delete(ctx, u))
   288  
   289  			objs, err := p.inv.ListObjects()
   290  			assert.NilError(t, err)
   291  			k.WaitOn(t, k.ObjsExist(unstructured.ToClientObjArray(objs...)))
   292  
   293  			return ctx
   294  		}).Feature()
   295  
   296  	f.Test(t, finalizer)
   297  }
   298  
   299  func TestUnpackedPalletController_Suspend(t *testing.T) {
   300  	var (
   301  		id string
   302  		v1 testPallet
   303  		v2 testPallet
   304  		u  = &whv1.UnpackedPallet{}
   305  	)
   306  
   307  	sus := f2.NewFeature("UnpackedPallet.spec.suspend").
   308  		Setup("Setup UnpackedPallet", func(ctx f2.Context, t *testing.T) f2.Context {
   309  			k := ktest.FromContextT(ctx, t)
   310  
   311  			id = fmt.Sprintf("suspend-%s", ctx.RunID)
   312  			v1 = createAndPushPallet(ctx, t, id, "v1", createLayer(t, layer.Runtime, minimalv1))
   313  			v2 = createAndPushPallet(ctx, t, id, "v2", createLayer(t, layer.Runtime, minimalv2))
   314  			u = unpackedPallet(ctx, t, v1.name, v1.pallet)
   315  
   316  			assert.NilError(t, k.Client.Create(ctx, u))
   317  			k.WaitOn(t, k.Check(u, kmp.HasInventory(v1.inv)))
   318  			k.WaitOn(t, k.InventoryExists(v1.inv))
   319  
   320  			return ctx
   321  		}).
   322  		Test("Becomes ready after setting spec.suspend", func(ctx f2.Context, t *testing.T) f2.Context {
   323  			k := ktest.FromContextT(ctx, t)
   324  
   325  			assert.NilError(t, k.Client.Get(
   326  				ctx, types.NamespacedName{Name: v1.name}, u,
   327  			))
   328  
   329  			patch := client.MergeFrom(u.DeepCopy())
   330  			u.Spec.Suspend = true
   331  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   332  
   333  			k.WaitOn(t, k.Check(u, unpackedPalletReady))
   334  
   335  			return ctx
   336  		}).
   337  		Test("New digests are not reconciled", func(ctx f2.Context, t *testing.T) f2.Context {
   338  			k := ktest.FromContextT(ctx, t)
   339  
   340  			assert.NilError(t, k.Client.Get(
   341  				ctx, types.NamespacedName{Name: v1.name}, u,
   342  			))
   343  
   344  			patch := client.MergeFrom(u.DeepCopy())
   345  			u.Spec.Digest = v2.digest
   346  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   347  
   348  			k.WaitOn(t, k.Check(u, func(o client.Object) cmp.Result {
   349  				u := o.(*whv1.UnpackedPallet)
   350  				if u.Status.LastApplied == v2.digest && u.Status.LastAttempted == v2.digest {
   351  					return cmp.ResultFailure("new digest was reconciled for suspended pallet")
   352  				}
   353  				return cmp.ResultSuccess
   354  			}), poll.WithTimeout(k.Timeout/2))
   355  
   356  			assert.Assert(t, kmp.HasInventory(v1.inv)(u).Success(),
   357  				"inventory should not have changed for suspended pallet")
   358  
   359  			objs, err := v1.inv.ListObjects()
   360  			assert.NilError(t, err)
   361  			for _, o := range objs {
   362  				assert.NilError(t, k.Client.Delete(ctx, o))
   363  			}
   364  			// Objects should stay deleted
   365  			k.WaitOn(t, k.ObjsDeleted(unstructured.ToClientObjArray(objs...)))
   366  
   367  			return ctx
   368  		}).Feature()
   369  
   370  	f.Test(t, sus)
   371  }
   372  
   373  func TestUnpackedPalletController_Dependencies(t *testing.T) {
   374  	var (
   375  		infraOnly  = "infra-only"
   376  		rtOnly     = "rt-only"
   377  		rtInfra    = "rt-infra"
   378  		rtCap      = "rt-cap"
   379  		rtInfraCap = "rt-infra-cap"
   380  		rootObj    *whv1.UnpackedPallet
   381  		objs       = make(map[string]*whv1.UnpackedPallet)
   382  		pkgs       = make(map[string]testPallet)
   383  	)
   384  
   385  	deps := f2.NewFeature("UnpackedPallet.spec.dependsOn").
   386  		Setup("Test Fixtures", func(ctx f2.Context, t *testing.T) f2.Context {
   387  			infraOnly = id(ctx, infraOnly)
   388  			rtOnly = id(ctx, rtOnly)
   389  			rtInfra = id(ctx, rtInfra)
   390  			rtCap = id(ctx, rtCap)
   391  			rtInfraCap = id(ctx, rtInfraCap)
   392  			root := id(ctx, "root")
   393  
   394  			pkgs[infraOnly] = createAndPushPallet(ctx, t, infraOnly, "v1", fakeInfraLayer(t))
   395  			objs[infraOnly] = unpackedPallet(ctx, t, infraOnly, pkgs[infraOnly].pallet,
   396  				whv1.WithUnpackOpts(whv1.UnpackOptions{Infra: true}))
   397  
   398  			pkgs[rtOnly] = createAndPushPallet(ctx, t, rtOnly, "v1",
   399  				createLayer(t, layer.Runtime, minimalv1))
   400  			objs[rtOnly] = unpackedPallet(ctx, t, rtOnly, pkgs[rtOnly].pallet)
   401  
   402  			pkgs[rtInfra] = createAndPushPallet(ctx, t, rtInfra, "v1",
   403  				createLayer(t, layer.Runtime, minimalv1),
   404  				fakeInfraLayer(t),
   405  			)
   406  			objs[rtInfra] = unpackedPallet(ctx, t, rtInfra, pkgs[rtInfra].pallet,
   407  				whv1.WithInfra(),
   408  				whv1.WithDeps(rtOnly),
   409  			)
   410  
   411  			pkgs[rtCap] = createAndPushPallet(ctx, t, rtCap, "v1",
   412  				createLayer(t, layer.Runtime, minimalv1),
   413  				fakeL5dLayer(t),
   414  			)
   415  			objs[rtCap] = unpackedPallet(ctx, t, rtCap, pkgs[rtCap].pallet,
   416  				whv1.WithCapabilities(string(l5dCap)),
   417  				whv1.WithDeps(rtOnly, rtInfra),
   418  			)
   419  
   420  			pkgs[rtInfraCap] = createAndPushPallet(ctx, t, rtInfraCap, "v1",
   421  				createLayer(t, layer.Runtime, minimalv1),
   422  				fakeInfraLayer(t),
   423  				fakeL5dLayer(t),
   424  			)
   425  			objs[rtInfraCap] = unpackedPallet(ctx, t, rtInfraCap, pkgs[rtInfraCap].pallet,
   426  				whv1.WithInfra(),
   427  				whv1.WithCapabilities(string(l5dCap)),
   428  				whv1.WithDeps(infraOnly, rtInfra),
   429  			)
   430  
   431  			rootPkg := createAndPushPallet(ctx, t, root, "v1",
   432  				createLayer(t, layer.Runtime, minimalv1))
   433  			rootObj = unpackedPallet(ctx, t, root, rootPkg.pallet,
   434  				whv1.WithDeps(infraOnly, rtCap, rtOnly, rtInfra, rtInfraCap))
   435  
   436  			return ctx
   437  		}).Test("Dependency Analysis", func(ctx f2.Context, t *testing.T) f2.Context {
   438  		k := ktest.FromContextT(ctx, t)
   439  
   440  		// Create root object first to intentionally make things harder on the
   441  		// reconciler.
   442  		assert.NilError(t, k.Client.Create(ctx, rootObj))
   443  		// Create objects root depends on
   444  		for _, obj := range objs {
   445  			assert.NilError(t, k.Client.Create(ctx, obj))
   446  		}
   447  
   448  		// If the root object reconciles, that means the rest of the chain should
   449  		// too.
   450  		k.WaitOn(t, k.Check(rootObj, unpackedPalletReady), poll.WithTimeout(k.Timeout*2))
   451  		// Double check our dependent objects actually reconciled.
   452  		for _, obj := range objs {
   453  			k.WaitOn(t, k.Check(obj, unpackedPalletReady))
   454  		}
   455  
   456  		return ctx
   457  	}).Feature()
   458  
   459  	f.Test(t, deps)
   460  }
   461  
   462  func TestUnpackedPalletController_ObjectPatching(t *testing.T) {
   463  	var u = &whv1.UnpackedPallet{}
   464  
   465  	finalizer := f2.NewFeature("Apply removes deleted  fields").
   466  		Setup("Set up UnpackedPallet", func(ctx f2.Context, t *testing.T) f2.Context {
   467  			k := ktest.FromContextT(ctx, t)
   468  			v1 := createAndPushPallet(ctx, t, fmt.Sprintf("patch-%s", ctx.RunID), "0.1.0",
   469  				createLayer(t, layer.Runtime, sapInitial))
   470  			u = unpackedPallet(ctx, t, v1.name, v1.pallet)
   471  			assert.NilError(t, k.Client.Create(ctx, u))
   472  
   473  			// pallet contains a single daemonset initially containing an envFrom field
   474  			ds := &appsv1.DaemonSet{ObjectMeta: metav1.ObjectMeta{Name: "nodeagent", Namespace: k.Namespace}}
   475  			k.WaitOn(t, k.ObjExists(ds))
   476  			envFrom := ds.Spec.Template.Spec.Containers[0].EnvFrom
   477  			if envFrom[0].SecretRef.Name != "ldkey" {
   478  				t.FailNow()
   479  			}
   480  
   481  			return ctx
   482  		}).
   483  		Test("Empty fields are removed when object is patched", func(ctx f2.Context, t *testing.T) f2.Context {
   484  			k := ktest.FromContextT(ctx, t)
   485  
   486  			// v2 removes the envFrom
   487  			v2 := createAndPushPallet(ctx, t, fmt.Sprintf("patch-%s", ctx.RunID), "0.2.0",
   488  				createLayer(t, layer.Runtime, sapFinal))
   489  			assert.NilError(t, k.Client.Get(
   490  				ctx, types.NamespacedName{Name: u.Name, Namespace: u.Namespace}, u,
   491  			))
   492  			patch := client.MergeFrom(u.DeepCopy())
   493  			u.Spec.Digest = v2.digest
   494  			assert.NilError(t, k.Client.Patch(ctx, u, patch))
   495  			k.WaitOn(t, k.Check(u, func(o client.Object) cmp.Result {
   496  				u := o.(*whv1.UnpackedPallet)
   497  				a := u.Spec.Artifact
   498  				if a.Digest != v2.digest {
   499  					return cmp.ResultFailure(fmt.Sprintf("digest should be %s. actual: %s", v2.digest, a.Digest))
   500  				}
   501  				return cmp.ResultSuccess
   502  			}))
   503  
   504  			ds := &appsv1.DaemonSet{ObjectMeta: metav1.ObjectMeta{Name: "nodeagent", Namespace: k.Namespace}}
   505  			k.WaitOn(t, k.Check(ds, func(o client.Object) cmp.Result {
   506  				ds := o.(*appsv1.DaemonSet)
   507  				envFrom := ds.Spec.Template.Spec.Containers[0].EnvFrom
   508  				if envFrom != nil {
   509  					return cmp.ResultFailure(fmt.Sprintf("envfrom should be removed. actual: %+v", envFrom))
   510  				}
   511  				return cmp.ResultSuccess
   512  			}))
   513  
   514  			return ctx
   515  		}).Feature()
   516  
   517  	f.Test(t, finalizer)
   518  }
   519  

View as plain text