istio.io/istio@v0.0.0-20240520182934-d79c90f27776/cni/pkg/nodeagent/informers_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package nodeagent
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/stretchr/testify/mock"
    24  	corev1 "k8s.io/api/core/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/types"
    27  
    28  	"istio.io/istio/cni/pkg/util"
    29  	"istio.io/istio/pkg/config/constants"
    30  	"istio.io/istio/pkg/kube"
    31  	"istio.io/istio/pkg/monitoring/monitortest"
    32  	"istio.io/istio/pkg/test/util/assert"
    33  )
    34  
    35  func TestExistingPodAddedWhenNsLabeled(t *testing.T) {
    36  	setupLogging()
    37  	NodeName = "testnode"
    38  	ctx, cancel := context.WithCancel(context.Background())
    39  	defer cancel()
    40  
    41  	pod := &corev1.Pod{
    42  		ObjectMeta: metav1.ObjectMeta{
    43  			Name:      "test",
    44  			Namespace: "test",
    45  		},
    46  		Spec: corev1.PodSpec{
    47  			NodeName: NodeName,
    48  		},
    49  		Status: corev1.PodStatus{
    50  			PodIP: "11.1.1.12",
    51  		},
    52  	}
    53  	ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test"}}
    54  
    55  	client := kube.NewFakeClient(ns, pod)
    56  
    57  	// We are expecting at most 1 calls to the mock, wait for them
    58  	wg, waitForMockCalls := NewWaitForNCalls(t, 1)
    59  	fs := &fakeServer{testWG: wg}
    60  
    61  	fs.On("AddPodToMesh",
    62  		ctx,
    63  		pod,
    64  		util.GetPodIPsIfPresent(pod),
    65  		"",
    66  	).Return(nil)
    67  
    68  	server := &meshDataplane{
    69  		kubeClient: client.Kube(),
    70  		netServer:  fs,
    71  	}
    72  
    73  	handlers := setupHandlers(ctx, client, server, "istio-system")
    74  	client.RunAndWait(ctx.Done())
    75  	go handlers.Start()
    76  
    77  	// label the namespace
    78  	labelsPatch := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`,
    79  		constants.DataplaneModeLabel, constants.DataplaneModeAmbient))
    80  	_, err := client.Kube().CoreV1().Namespaces().Patch(ctx, ns.Name,
    81  		types.MergePatchType, labelsPatch, metav1.PatchOptions{})
    82  	assert.NoError(t, err)
    83  
    84  	waitForMockCalls()
    85  
    86  	assertPodAnnotated(t, client, pod)
    87  
    88  	// Assert expected calls actually made
    89  	fs.AssertExpectations(t)
    90  }
    91  
    92  func TestExistingPodAddedWhenDualStack(t *testing.T) {
    93  	setupLogging()
    94  	NodeName = "testnode"
    95  	ctx, cancel := context.WithCancel(context.Background())
    96  	defer cancel()
    97  
    98  	pod := &corev1.Pod{
    99  		ObjectMeta: metav1.ObjectMeta{
   100  			Name:      "test",
   101  			Namespace: "test",
   102  		},
   103  		Spec: corev1.PodSpec{
   104  			NodeName: NodeName,
   105  		},
   106  		Status: corev1.PodStatus{
   107  			PodIPs: []corev1.PodIP{
   108  				{
   109  					IP: "11.1.1.12",
   110  				},
   111  			},
   112  		},
   113  	}
   114  	ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test"}}
   115  
   116  	client := kube.NewFakeClient(ns, pod)
   117  
   118  	// We are expecting at most 1 calls to the mock, wait for them
   119  	wg, waitForMockCalls := NewWaitForNCalls(t, 1)
   120  
   121  	fs := &fakeServer{testWG: wg}
   122  
   123  	fs.On("AddPodToMesh",
   124  		ctx,
   125  		pod,
   126  		util.GetPodIPsIfPresent(pod),
   127  		"",
   128  	).Return(nil)
   129  
   130  	server := &meshDataplane{
   131  		kubeClient: client.Kube(),
   132  		netServer:  fs,
   133  	}
   134  
   135  	fs.Start(ctx)
   136  	handlers := setupHandlers(ctx, client, server, "istio-system")
   137  	client.RunAndWait(ctx.Done())
   138  	go handlers.Start()
   139  
   140  	// label the namespace
   141  	labelsPatch := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`,
   142  		constants.DataplaneModeLabel, constants.DataplaneModeAmbient))
   143  	_, err := client.Kube().CoreV1().Namespaces().Patch(ctx, ns.Name,
   144  		types.MergePatchType, labelsPatch, metav1.PatchOptions{})
   145  	assert.NoError(t, err)
   146  
   147  	waitForMockCalls()
   148  
   149  	assertPodAnnotated(t, client, pod)
   150  
   151  	// Assert expected calls actually made
   152  	fs.AssertExpectations(t)
   153  }
   154  
   155  func TestExistingPodNotAddedIfNoIPInAnyStatusField(t *testing.T) {
   156  	setupLogging()
   157  	NodeName = "testnode"
   158  	ctx, cancel := context.WithCancel(context.Background())
   159  	defer cancel()
   160  
   161  	mt := monitortest.New(t)
   162  
   163  	pod := &corev1.Pod{
   164  		ObjectMeta: metav1.ObjectMeta{
   165  			Name:      "test",
   166  			Namespace: "test",
   167  		},
   168  		Spec: corev1.PodSpec{
   169  			NodeName: NodeName,
   170  		},
   171  		Status: corev1.PodStatus{
   172  			PodIPs: []corev1.PodIP{},
   173  			PodIP:  "",
   174  		},
   175  	}
   176  	ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test"}}
   177  
   178  	client := kube.NewFakeClient(ns, pod)
   179  
   180  	fs := &fakeServer{}
   181  
   182  	server := &meshDataplane{
   183  		kubeClient: client.Kube(),
   184  		netServer:  fs,
   185  	}
   186  
   187  	handlers := setupHandlers(ctx, client, server, "istio-system")
   188  	client.RunAndWait(ctx.Done())
   189  	go handlers.Start()
   190  
   191  	// label the namespace
   192  	labelsPatch := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`,
   193  		constants.DataplaneModeLabel, constants.DataplaneModeAmbient))
   194  	_, err := client.Kube().CoreV1().Namespaces().Patch(ctx, ns.Name,
   195  		types.MergePatchType, labelsPatch, metav1.PatchOptions{})
   196  	assert.NoError(t, err)
   197  
   198  	// wait until at least one add event happens
   199  	mt.Assert(EventTotals.Name(), map[string]string{"type": "add"}, monitortest.AtLeast(1))
   200  
   201  	assertPodNotAnnotated(t, client, pod)
   202  
   203  	// Assert expected calls (not) actually made
   204  	fs.AssertExpectations(t)
   205  }
   206  
   207  func TestExistingPodRemovedWhenNsUnlabeled(t *testing.T) {
   208  	setupLogging()
   209  	mt := monitortest.New(t)
   210  	NodeName = "testnode"
   211  
   212  	ctx, cancel := context.WithCancel(context.Background())
   213  	defer cancel()
   214  
   215  	pod := &corev1.Pod{
   216  		ObjectMeta: metav1.ObjectMeta{
   217  			Name:      "test",
   218  			Namespace: "test",
   219  		},
   220  		Spec: corev1.PodSpec{
   221  			NodeName: NodeName,
   222  		},
   223  		Status: corev1.PodStatus{
   224  			PodIP: "11.1.1.12",
   225  		},
   226  	}
   227  	ns := &corev1.Namespace{
   228  		ObjectMeta: metav1.ObjectMeta{Name: "test"},
   229  		// TODO: once we if the add pod bug, re-enable this and remove the patch below
   230  		//		Labels: map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeAmbient},
   231  
   232  	}
   233  
   234  	client := kube.NewFakeClient(ns, pod)
   235  
   236  	// We are expecting at most 2 calls to the mock, wait for them
   237  	wg, waitForMockCalls := NewWaitForNCalls(t, 2)
   238  	fs := &fakeServer{testWG: wg}
   239  
   240  	fs.On("AddPodToMesh",
   241  		ctx,
   242  		pod,
   243  		util.GetPodIPsIfPresent(pod),
   244  		"",
   245  	).Return(nil)
   246  
   247  	server := &meshDataplane{
   248  		kubeClient: client.Kube(),
   249  		netServer:  fs,
   250  	}
   251  
   252  	handlers := setupHandlers(ctx, client, server, "istio-system")
   253  	client.RunAndWait(ctx.Done())
   254  	go handlers.Start()
   255  	// wait until pod add was called
   256  	mt.Assert(EventTotals.Name(), map[string]string{"type": "update"}, monitortest.AtLeast(1))
   257  
   258  	log.Debug("labeling namespace")
   259  	_, err := client.Kube().CoreV1().Namespaces().Patch(ctx, ns.Name,
   260  		types.MergePatchType, []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`,
   261  			constants.DataplaneModeLabel, constants.DataplaneModeAmbient)), metav1.PatchOptions{})
   262  	assert.NoError(t, err)
   263  
   264  	// wait for an update event
   265  	mt.Assert(EventTotals.Name(), map[string]string{"type": "update"}, monitortest.AtLeast(2))
   266  
   267  	// wait for the pod to be annotated
   268  	// after Pod annotated, another update event will be triggered.
   269  	assertPodAnnotated(t, client, pod)
   270  
   271  	// Assert expected calls actually made
   272  	fs.AssertExpectations(t)
   273  
   274  	// unlabelling the namespace should cause only one RemovePodFromMesh to happen
   275  	fs.On("RemovePodFromMesh",
   276  		ctx,
   277  		mock.Anything,
   278  	).Once().Return(nil)
   279  
   280  	// unlabel the namespace
   281  	labelsPatch := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":null}}}`,
   282  		constants.DataplaneModeLabel))
   283  	_, err = client.Kube().CoreV1().Namespaces().Patch(ctx, ns.Name,
   284  		types.MergePatchType, labelsPatch, metav1.PatchOptions{})
   285  	assert.NoError(t, err)
   286  
   287  	// wait for another two update events
   288  	// total 3 update at before unlabel point: 1. init ns reconcile 2. ns label reconcile 3. pod annotation update
   289  	mt.Assert(EventTotals.Name(), map[string]string{"type": "update"}, monitortest.AtLeast(5))
   290  
   291  	waitForMockCalls()
   292  
   293  	assertPodNotAnnotated(t, client, pod)
   294  
   295  	// Assert expected calls actually made
   296  	fs.AssertExpectations(t)
   297  }
   298  
   299  func TestExistingPodRemovedWhenPodAnnotated(t *testing.T) {
   300  	setupLogging()
   301  	mt := monitortest.New(t)
   302  	NodeName = "testnode"
   303  
   304  	ctx, cancel := context.WithCancel(context.Background())
   305  	defer cancel()
   306  
   307  	pod := &corev1.Pod{
   308  		ObjectMeta: metav1.ObjectMeta{
   309  			Name:      "test",
   310  			Namespace: "test",
   311  		},
   312  		Spec: corev1.PodSpec{
   313  			NodeName: NodeName,
   314  		},
   315  		Status: corev1.PodStatus{
   316  			PodIP: "11.1.1.12",
   317  		},
   318  	}
   319  	ns := &corev1.Namespace{
   320  		ObjectMeta: metav1.ObjectMeta{Name: "test"},
   321  		// TODO: once we if the add pod bug, re-enable this and remove the patch below
   322  		//		Labels: map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeAmbient},
   323  
   324  	}
   325  
   326  	client := kube.NewFakeClient(ns, pod)
   327  
   328  	// We are expecting at most 2 calls to the mock, wait for them
   329  	wg, waitForMockCalls := NewWaitForNCalls(t, 2)
   330  	fs := &fakeServer{testWG: wg}
   331  
   332  	fs.On("AddPodToMesh",
   333  		ctx,
   334  		pod,
   335  		util.GetPodIPsIfPresent(pod),
   336  		"",
   337  	).Return(nil)
   338  
   339  	server := &meshDataplane{
   340  		kubeClient: client.Kube(),
   341  		netServer:  fs,
   342  	}
   343  
   344  	handlers := setupHandlers(ctx, client, server, "istio-system")
   345  	client.RunAndWait(ctx.Done())
   346  	go handlers.Start()
   347  	// wait until pod add was called
   348  	mt.Assert(EventTotals.Name(), map[string]string{"type": "update"}, monitortest.AtLeast(1))
   349  
   350  	log.Debug("labeling namespace")
   351  	_, err := client.Kube().CoreV1().Namespaces().Patch(ctx, ns.Name,
   352  		types.MergePatchType, []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`,
   353  			constants.DataplaneModeLabel, constants.DataplaneModeAmbient)), metav1.PatchOptions{})
   354  	assert.NoError(t, err)
   355  
   356  	// wait for an update event
   357  	mt.Assert(EventTotals.Name(), map[string]string{"type": "update"}, monitortest.AtLeast(2))
   358  
   359  	// wait for the pod to be annotated
   360  	// after Pod annotated, another update event will be triggered.
   361  	assertPodAnnotated(t, client, pod)
   362  
   363  	// Assert expected calls actually made
   364  	fs.AssertExpectations(t)
   365  
   366  	// annotate Pod as disabled should cause only one RemovePodFromMesh to happen
   367  	fs.On("RemovePodFromMesh",
   368  		ctx,
   369  		mock.Anything,
   370  	).Once().Return(nil)
   371  
   372  	// label the pod for exclusion
   373  	labelsPatch := []byte(fmt.Sprintf(`{"metadata":{"labels":{"%s":"%s"}}}`,
   374  		constants.DataplaneModeLabel, constants.DataplaneModeNone))
   375  	_, err = client.Kube().CoreV1().Pods(pod.Namespace).Patch(ctx, pod.Name,
   376  		types.MergePatchType, labelsPatch, metav1.PatchOptions{})
   377  	assert.NoError(t, err)
   378  
   379  	// wait for an update events
   380  	// total 3 update at before unlabel point: 1. init ns reconcile 2. ns label reconcile 3. pod annotation update
   381  	mt.Assert(EventTotals.Name(), map[string]string{"type": "update"}, monitortest.AtLeast(4))
   382  
   383  	waitForMockCalls()
   384  
   385  	assertPodNotAnnotated(t, client, pod)
   386  
   387  	// patch a test label to emulate a POD update event
   388  	_, err = client.Kube().CoreV1().Pods(pod.Namespace).Patch(ctx, pod.Name,
   389  		types.MergePatchType, []byte(`{"metadata":{"labels":{"test":"update"}}}`), metav1.PatchOptions{})
   390  	assert.NoError(t, err)
   391  
   392  	// wait for an update events
   393  	mt.Assert(EventTotals.Name(), map[string]string{"type": "update"}, monitortest.AtLeast(5))
   394  
   395  	assertPodNotAnnotated(t, client, pod)
   396  
   397  	// Assert expected calls actually made
   398  	fs.AssertExpectations(t)
   399  }
   400  
   401  func TestAmbientEnabledReturnsPodIfEnabled(t *testing.T) {
   402  	setupLogging()
   403  	NodeName = "testnode"
   404  
   405  	ctx, cancel := context.WithCancel(context.Background())
   406  	defer cancel()
   407  
   408  	pod := &corev1.Pod{
   409  		ObjectMeta: metav1.ObjectMeta{
   410  			Name:      "test",
   411  			Namespace: "test",
   412  			UID:       "1234",
   413  		},
   414  		Spec: corev1.PodSpec{
   415  			NodeName: NodeName,
   416  		},
   417  		Status: corev1.PodStatus{
   418  			PodIP: "11.1.1.12",
   419  		},
   420  	}
   421  	ns := &corev1.Namespace{
   422  		ObjectMeta: metav1.ObjectMeta{
   423  			Name:   "test",
   424  			Labels: map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeAmbient},
   425  		},
   426  	}
   427  
   428  	client := kube.NewFakeClient(ns, pod)
   429  	fs := &fakeServer{}
   430  	fs.Start(ctx)
   431  	server := &meshDataplane{
   432  		kubeClient: client.Kube(),
   433  		netServer:  fs,
   434  	}
   435  
   436  	handlers := setupHandlers(ctx, client, server, "istio-system")
   437  	client.RunAndWait(ctx.Done())
   438  	_, err := handlers.GetPodIfAmbient(pod.Name, ns.Name)
   439  
   440  	assert.NoError(t, err)
   441  }
   442  
   443  func TestAmbientEnabledReturnsNoPodIfNotEnabled(t *testing.T) {
   444  	setupLogging()
   445  	NodeName = "testnode"
   446  
   447  	ctx, cancel := context.WithCancel(context.Background())
   448  	defer cancel()
   449  
   450  	pod := &corev1.Pod{
   451  		ObjectMeta: metav1.ObjectMeta{
   452  			Name:      "test",
   453  			Namespace: "test",
   454  			UID:       "1234",
   455  			Labels:    map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeNone},
   456  		},
   457  		Spec: corev1.PodSpec{
   458  			NodeName: NodeName,
   459  		},
   460  		Status: corev1.PodStatus{
   461  			PodIP: "11.1.1.12",
   462  		},
   463  	}
   464  	ns := &corev1.Namespace{
   465  		ObjectMeta: metav1.ObjectMeta{
   466  			Name:   "test",
   467  			Labels: map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeAmbient},
   468  		},
   469  	}
   470  
   471  	client := kube.NewFakeClient(ns, pod)
   472  	fs := &fakeServer{}
   473  	fs.Start(ctx)
   474  	server := &meshDataplane{
   475  		kubeClient: client.Kube(),
   476  		netServer:  fs,
   477  	}
   478  
   479  	handlers := setupHandlers(ctx, client, server, "istio-system")
   480  	client.RunAndWait(ctx.Done())
   481  	disabledPod, err := handlers.GetPodIfAmbient(pod.Name, ns.Name)
   482  
   483  	assert.NoError(t, err)
   484  	assert.Equal(t, disabledPod, nil)
   485  }
   486  
   487  func TestAmbientEnabledReturnsErrorIfBogusNS(t *testing.T) {
   488  	setupLogging()
   489  	NodeName = "testnode"
   490  
   491  	ctx, cancel := context.WithCancel(context.Background())
   492  	defer cancel()
   493  
   494  	pod := &corev1.Pod{
   495  		ObjectMeta: metav1.ObjectMeta{
   496  			Name:      "test",
   497  			Namespace: "test",
   498  			UID:       "1234",
   499  			Labels:    map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeNone},
   500  		},
   501  		Spec: corev1.PodSpec{
   502  			NodeName: NodeName,
   503  		},
   504  		Status: corev1.PodStatus{
   505  			PodIP: "11.1.1.12",
   506  		},
   507  	}
   508  	ns := &corev1.Namespace{
   509  		ObjectMeta: metav1.ObjectMeta{
   510  			Name:   "test",
   511  			Labels: map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeAmbient},
   512  		},
   513  	}
   514  
   515  	client := kube.NewFakeClient(ns, pod)
   516  	fs := &fakeServer{}
   517  	fs.Start(ctx)
   518  	server := &meshDataplane{
   519  		kubeClient: client.Kube(),
   520  		netServer:  fs,
   521  	}
   522  
   523  	handlers := setupHandlers(ctx, client, server, "istio-system")
   524  	client.RunAndWait(ctx.Done())
   525  	disabledPod, err := handlers.GetPodIfAmbient(pod.Name, "what")
   526  
   527  	assert.Error(t, err)
   528  	assert.Equal(t, disabledPod, nil)
   529  }
   530  
   531  func TestExistingPodAddedWhenItPreExists(t *testing.T) {
   532  	setupLogging()
   533  	NodeName = "testnode"
   534  
   535  	mt := monitortest.New(t)
   536  
   537  	ctx, cancel := context.WithCancel(context.Background())
   538  	defer cancel()
   539  
   540  	pod := &corev1.Pod{
   541  		ObjectMeta: metav1.ObjectMeta{
   542  			Name:      "test",
   543  			Namespace: "test",
   544  		},
   545  		Spec: corev1.PodSpec{
   546  			NodeName: NodeName,
   547  		},
   548  		Status: corev1.PodStatus{
   549  			PodIP: "11.1.1.12",
   550  		},
   551  	}
   552  	ns := &corev1.Namespace{
   553  		ObjectMeta: metav1.ObjectMeta{
   554  			Name:   "test",
   555  			Labels: map[string]string{constants.DataplaneModeLabel: constants.DataplaneModeAmbient},
   556  		},
   557  	}
   558  
   559  	client := kube.NewFakeClient(ns, pod)
   560  
   561  	// We are expecting at most 1 calls to the mock, wait for them
   562  	wg, waitForMockCalls := NewWaitForNCalls(t, 1)
   563  	fs := &fakeServer{testWG: wg}
   564  
   565  	fs.On("AddPodToMesh",
   566  		ctx,
   567  		pod,
   568  		util.GetPodIPsIfPresent(pod),
   569  		"",
   570  	).Return(nil)
   571  
   572  	server := &meshDataplane{
   573  		kubeClient: client.Kube(),
   574  		netServer:  fs,
   575  	}
   576  
   577  	handlers := setupHandlers(ctx, client, server, "istio-system")
   578  	client.RunAndWait(ctx.Done())
   579  	go handlers.Start()
   580  
   581  	waitForMockCalls()
   582  	// wait until pod add was called
   583  	mt.Assert(EventTotals.Name(), map[string]string{"type": "add"}, monitortest.AtLeast(1))
   584  
   585  	assertPodAnnotated(t, client, pod)
   586  
   587  	// check expectations on mocked calls
   588  	fs.AssertExpectations(t)
   589  }
   590  
   591  func assertPodAnnotated(t *testing.T, client kube.Client, pod *corev1.Pod) {
   592  	for i := 0; i < 5; i++ {
   593  		p, err := client.Kube().CoreV1().Pods(pod.Namespace).Get(context.Background(), pod.Name, metav1.GetOptions{})
   594  		if err != nil {
   595  			t.Fatal(err)
   596  		}
   597  		if p.Annotations[constants.AmbientRedirection] == constants.AmbientRedirectionEnabled {
   598  			return
   599  		}
   600  		time.Sleep(1 * time.Second)
   601  	}
   602  	t.Fatal("Pod not annotated")
   603  }
   604  
   605  func assertPodNotAnnotated(t *testing.T, client kube.Client, pod *corev1.Pod) {
   606  	for i := 0; i < 5; i++ {
   607  		p, err := client.Kube().CoreV1().Pods(pod.Namespace).Get(context.Background(), pod.Name, metav1.GetOptions{})
   608  		if err != nil {
   609  			t.Fatal(err)
   610  		}
   611  		if p.Annotations[constants.AmbientRedirection] != constants.AmbientRedirectionEnabled {
   612  			return
   613  		}
   614  		time.Sleep(1 * time.Second)
   615  	}
   616  	t.Fatal("Pod annotated")
   617  }