diff --git a/pkg/agent/controller/packetsampling/packetin.go b/pkg/agent/controller/packetsampling/packetin.go index 073a80b5814..f1d494d070e 100644 --- a/pkg/agent/controller/packetsampling/packetin.go +++ b/pkg/agent/controller/packetsampling/packetin.go @@ -87,23 +87,20 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (_ *packetSamplingSta tag = uint8(value) } c.runningPacketSamplingsMutex.Lock() + defer c.runningPacketSamplingsMutex.Unlock() psState, exists := c.runningPacketSamplings[tag] - if exists { - if psState.numCapturedPackets == psState.maxNumCapturedPackets { - c.runningPacketSamplingsMutex.Unlock() - return nil, true, nil - } - psState.numCapturedPackets++ - if psState.numCapturedPackets == psState.maxNumCapturedPackets { - err := c.ofClient.UninstallPacketSamplingFlows(tag) - if err != nil { - return nil, false, fmt.Errorf("uninstall PacketSampling ovs flow failed: %v", err) - } - } - } - c.runningPacketSamplingsMutex.Unlock() if !exists { return nil, false, fmt.Errorf("PacketSampling for dataplane tag %d not found in cache", tag) } + if psState.numCapturedPackets == psState.maxNumCapturedPackets { + return nil, true, nil + } + psState.numCapturedPackets++ + if psState.numCapturedPackets == psState.maxNumCapturedPackets { + err := c.ofClient.UninstallPacketSamplingFlows(tag) + if err != nil { + return nil, false, fmt.Errorf("uninstall PacketSampling ovs flow failed: %v", err) + } + } return psState, false, nil } diff --git a/pkg/agent/controller/packetsampling/packetin_test.go b/pkg/agent/controller/packetsampling/packetin_test.go index d86df2fba7c..5377f20037b 100644 --- a/pkg/agent/controller/packetsampling/packetin_test.go +++ b/pkg/agent/controller/packetsampling/packetin_test.go @@ -16,6 +16,8 @@ package packetsampling import ( "context" + "encoding/binary" + "fmt" "net" "testing" @@ -33,10 +35,8 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/klog/v2" "antrea.io/antrea/pkg/agent/config" - "antrea.io/antrea/pkg/agent/openflow" openflowtest "antrea.io/antrea/pkg/agent/openflow/testing" crdv1alpha1 "antrea.io/antrea/pkg/apis/crd/v1alpha1" ) @@ -46,36 +46,35 @@ const ( ) const ( - testTag = uint8(1) + testTag = uint8(3) testUID = "1-2-3-4" - testSFTPUrl = "sftp://10.220.175.92:22/root/packetsamplings" + testSFTPUrl = "sftp://127.0.0.1:22/root/packetsamplings" ) -var ( - // parse to tag(1) - testTagData = []byte{0x11, 0x00, 0x00, 0x11} -) +// generatePacketInMatchFromTag reverse the packetIn message/matcher -> REG4/tag value path +// to generate test matchers. It follows the following process: +// 1. shift bits to generate uint32, which represents data in REG4 and another REG (unrelated) +// 2. convert uint32 to bytes(bigEndian), which will be the Match value/mask. +// 3. generate MatchField from the bytes. +func generatePacketInMatchFromTag(tag uint8) *openflow15.MatchField { + value := uint32(tag) << 28 + regID := 4 + data := make([]byte, 8) + binary.BigEndian.PutUint32(data, value) -func genMatchers() []openflow15.MatchField { - m := generateMatch(openflow.PacketSamplingMark.GetRegID(), testTagData) - matchers := []openflow15.MatchField{m} - return matchers -} - -func generateMatch(regID int, data []byte) openflow15.MatchField { - baseData := make([]byte, 8, 8) - if regID%2 == 0 { - copy(baseData[0:4], data) - } else { - copy(baseData[4:8], data) - } - return openflow15.MatchField{ - Class: openflow15.OXM_CLASS_PACKET_REGS, - // convert reg (4-byte) ID to xreg (8-byte) ID + m := openflow15.MatchField{ + Class: openflow15.OXM_CLASS_PACKET_REGS, Field: uint8(regID / 2), HasMask: false, - Value: &openflow15.ByteArrayField{Data: baseData}, + Value: &openflow15.ByteArrayField{Data: data}, } + return &m +} + +func genMatchers() []openflow15.MatchField { + // m := generateMatch(openflow.PacketSamplingMark.GetRegID(), testTagData) + matchers := []openflow15.MatchField{*generatePacketInMatchFromTag(testTag)} + return matchers } func getTestPacketBytes(dstIP string) []byte { @@ -151,10 +150,17 @@ func generateTestSecret() *v1.Secret { } type testUploader struct { + url string + fileName string } func (uploader *testUploader) Upload(url string, fileName string, config *ssh.ClientConfig, outputFile afero.File) error { - klog.Info("Called test uploader") + if url != uploader.url { + return fmt.Errorf("expected url: %s for uploader, got: %s", uploader.url, url) + } + if fileName != uploader.fileName { + return fmt.Errorf("expected filename: %s for uploader, got: %s", uploader.fileName, fileName) + } return nil } @@ -177,15 +183,16 @@ func TestHandlePacketSamplingPacketIn(t *testing.T) { } tests := []struct { - name string - networkConfig *config.NetworkConfig - nodeConfig *config.NodeConfig - psState *packetSamplingState - pktIn *ofctrl.PacketIn - expectedPS *crdv1alpha1.PacketSampling - expectedErrStr string - expectedCalls func(mockOFClient *openflowtest.MockClient) - expectedNum int32 + name string + networkConfig *config.NetworkConfig + nodeConfig *config.NodeConfig + psState *packetSamplingState + pktIn *ofctrl.PacketIn + expectedPS *crdv1alpha1.PacketSampling + expectedErrStr string + expectedCalls func(mockOFClient *openflowtest.MockClient) + expectedNum int32 + expectedUploader *testUploader }{ { name: "invalid packets", @@ -228,6 +235,10 @@ func TestHandlePacketSamplingPacketIn(t *testing.T) { expectedCalls: func(mockOFClient *openflowtest.MockClient) { mockOFClient.EXPECT().UninstallPacketSamplingFlows(testTag) }, + expectedUploader: &testUploader{ + fileName: testUID + ".pcapng", + url: testSFTPUrl, + }, }, } @@ -243,6 +254,8 @@ func TestHandlePacketSamplingPacketIn(t *testing.T) { psc.crdInformerFactory.WaitForCacheSync(stopCh) psc.runningPacketSamplings[tt.psState.tag] = tt.psState + psc.sftpUploader = tt.expectedUploader + err := psc.HandlePacketIn(tt.pktIn) if err == nil { assert.Equal(t, tt.expectedErrStr, "") diff --git a/pkg/agent/controller/packetsampling/packetsampling_controller.go b/pkg/agent/controller/packetsampling/packetsampling_controller.go index dbe29a5c3d7..faad8987159 100644 --- a/pkg/agent/controller/packetsampling/packetsampling_controller.go +++ b/pkg/agent/controller/packetsampling/packetsampling_controller.go @@ -189,6 +189,11 @@ func (c *Controller) Run(stopCh <-chan struct{}) { return } + // cleanup existing packets file first. successful PacketSampling will upload them to the target file server. + // others are useless once we restart the controller. + if err := defaultFS.RemoveAll(packetDirectory); err != nil { + klog.ErrorS(err, "Remove packets dir error", "directory", packetDirectory) + } err := defaultFS.MkdirAll(packetDirectory, 0755) if err != nil { klog.ErrorS(err, "Couldn't create directory for storing sampling packets", "directory", packetDirectory) @@ -280,8 +285,10 @@ func (c *Controller) cleanupPacketSampling(psName string) { if err != nil { klog.ErrorS(err, "Error cleaning up flows for PacketSampling", "name", psName) } - if err := psState.pcapngFile.Close(); err != nil { - klog.ErrorS(err, "Error closing pcap file", "name", psName) + if psState.pcapngFile != nil { + if err := psState.pcapngFile.Close(); err != nil { + klog.ErrorS(err, "Error closing pcap file", "name", psName) + } } } } @@ -663,8 +670,8 @@ func (c *Controller) deallocateTag(name string, tag uint8) { } func (c *Controller) getTagForPacketSampling(name string) uint8 { - c.runningPacketSamplingsMutex.Lock() - defer c.runningPacketSamplingsMutex.Unlock() + c.runningPacketSamplingsMutex.RLock() + defer c.runningPacketSamplingsMutex.RUnlock() for tag, state := range c.runningPacketSamplings { if state != nil && state.name == name { // The packetsampling request has been processed already. diff --git a/pkg/agent/controller/packetsampling/packetsampling_controller_test.go b/pkg/agent/controller/packetsampling/packetsampling_controller_test.go index 27d486873a9..bb6fdd72920 100644 --- a/pkg/agent/controller/packetsampling/packetsampling_controller_test.go +++ b/pkg/agent/controller/packetsampling/packetsampling_controller_test.go @@ -22,6 +22,7 @@ import ( "testing" "time" + "antrea.io/libOpenflow/protocol" "github.com/google/gopacket/layers" "github.com/google/gopacket/pcapgo" "github.com/spf13/afero" @@ -37,7 +38,6 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" "k8s.io/klog/v2" - "antrea.io/libOpenflow/protocol" "antrea.io/antrea/pkg/agent/config" "antrea.io/antrea/pkg/agent/interfacestore" diff --git a/pkg/apiserver/handlers/featuregates/handler_test.go b/pkg/apiserver/handlers/featuregates/handler_test.go index b06d3ecaeb1..831c3a80195 100644 --- a/pkg/apiserver/handlers/featuregates/handler_test.go +++ b/pkg/apiserver/handlers/featuregates/handler_test.go @@ -202,7 +202,6 @@ func Test_getControllerGatesResponse(t *testing.T) { {Component: "controller", Name: "Multicluster", Status: "Disabled", Version: "ALPHA"}, {Component: "controller", Name: "NetworkPolicyStats", Status: "Enabled", Version: "BETA"}, {Component: "controller", Name: "NodeIPAM", Status: "Enabled", Version: "BETA"}, - {Component: "controller", Name: "PacketSampling", Status: "Disabled", Version: "ALPHA"}, {Component: "controller", Name: "ServiceExternalIP", Status: "Disabled", Version: "ALPHA"}, {Component: "controller", Name: "SupportBundleCollection", Status: "Disabled", Version: "ALPHA"}, {Component: "controller", Name: "Traceflow", Status: "Enabled", Version: "BETA"}, diff --git a/pkg/client/clientset/versioned/typed/crd/v1alpha1/fake/fake_packetsampling.go b/pkg/client/clientset/versioned/typed/crd/v1alpha1/fake/fake_packetsampling.go new file mode 100644 index 00000000000..ddd5d60d88a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/crd/v1alpha1/fake/fake_packetsampling.go @@ -0,0 +1,130 @@ +// Copyright 2024 Antrea Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "antrea.io/antrea/pkg/apis/crd/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakePacketSamplings implements PacketSamplingInterface +type FakePacketSamplings struct { + Fake *FakeCrdV1alpha1 +} + +var packetsamplingsResource = v1alpha1.SchemeGroupVersion.WithResource("packetsamplings") + +var packetsamplingsKind = v1alpha1.SchemeGroupVersion.WithKind("PacketSampling") + +// Get takes name of the packetSampling, and returns the corresponding packetSampling object, and an error if there is any. +func (c *FakePacketSamplings) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PacketSampling, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(packetsamplingsResource, name), &v1alpha1.PacketSampling{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PacketSampling), err +} + +// List takes label and field selectors, and returns the list of PacketSamplings that match those selectors. +func (c *FakePacketSamplings) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PacketSamplingList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(packetsamplingsResource, packetsamplingsKind, opts), &v1alpha1.PacketSamplingList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.PacketSamplingList{ListMeta: obj.(*v1alpha1.PacketSamplingList).ListMeta} + for _, item := range obj.(*v1alpha1.PacketSamplingList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested packetSamplings. +func (c *FakePacketSamplings) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(packetsamplingsResource, opts)) +} + +// Create takes the representation of a packetSampling and creates it. Returns the server's representation of the packetSampling, and an error, if there is any. +func (c *FakePacketSamplings) Create(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.CreateOptions) (result *v1alpha1.PacketSampling, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(packetsamplingsResource, packetSampling), &v1alpha1.PacketSampling{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PacketSampling), err +} + +// Update takes the representation of a packetSampling and updates it. Returns the server's representation of the packetSampling, and an error, if there is any. +func (c *FakePacketSamplings) Update(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.UpdateOptions) (result *v1alpha1.PacketSampling, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(packetsamplingsResource, packetSampling), &v1alpha1.PacketSampling{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PacketSampling), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakePacketSamplings) UpdateStatus(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.UpdateOptions) (*v1alpha1.PacketSampling, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(packetsamplingsResource, "status", packetSampling), &v1alpha1.PacketSampling{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PacketSampling), err +} + +// Delete takes name of the packetSampling and deletes it. Returns an error if one occurs. +func (c *FakePacketSamplings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(packetsamplingsResource, name, opts), &v1alpha1.PacketSampling{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakePacketSamplings) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(packetsamplingsResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.PacketSamplingList{}) + return err +} + +// Patch applies the patch and returns the patched packetSampling. +func (c *FakePacketSamplings) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PacketSampling, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(packetsamplingsResource, name, pt, data, subresources...), &v1alpha1.PacketSampling{}) + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.PacketSampling), err +} diff --git a/pkg/client/clientset/versioned/typed/crd/v1alpha1/packetsampling.go b/pkg/client/clientset/versioned/typed/crd/v1alpha1/packetsampling.go new file mode 100644 index 00000000000..75a55ca1891 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/crd/v1alpha1/packetsampling.go @@ -0,0 +1,182 @@ +// Copyright 2024 Antrea Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "antrea.io/antrea/pkg/apis/crd/v1alpha1" + scheme "antrea.io/antrea/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// PacketSamplingsGetter has a method to return a PacketSamplingInterface. +// A group's client should implement this interface. +type PacketSamplingsGetter interface { + PacketSamplings() PacketSamplingInterface +} + +// PacketSamplingInterface has methods to work with PacketSampling resources. +type PacketSamplingInterface interface { + Create(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.CreateOptions) (*v1alpha1.PacketSampling, error) + Update(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.UpdateOptions) (*v1alpha1.PacketSampling, error) + UpdateStatus(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.UpdateOptions) (*v1alpha1.PacketSampling, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.PacketSampling, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.PacketSamplingList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PacketSampling, err error) + PacketSamplingExpansion +} + +// packetSamplings implements PacketSamplingInterface +type packetSamplings struct { + client rest.Interface +} + +// newPacketSamplings returns a PacketSamplings +func newPacketSamplings(c *CrdV1alpha1Client) *packetSamplings { + return &packetSamplings{ + client: c.RESTClient(), + } +} + +// Get takes name of the packetSampling, and returns the corresponding packetSampling object, and an error if there is any. +func (c *packetSamplings) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.PacketSampling, err error) { + result = &v1alpha1.PacketSampling{} + err = c.client.Get(). + Resource("packetsamplings"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of PacketSamplings that match those selectors. +func (c *packetSamplings) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.PacketSamplingList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.PacketSamplingList{} + err = c.client.Get(). + Resource("packetsamplings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested packetSamplings. +func (c *packetSamplings) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("packetsamplings"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a packetSampling and creates it. Returns the server's representation of the packetSampling, and an error, if there is any. +func (c *packetSamplings) Create(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.CreateOptions) (result *v1alpha1.PacketSampling, err error) { + result = &v1alpha1.PacketSampling{} + err = c.client.Post(). + Resource("packetsamplings"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(packetSampling). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a packetSampling and updates it. Returns the server's representation of the packetSampling, and an error, if there is any. +func (c *packetSamplings) Update(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.UpdateOptions) (result *v1alpha1.PacketSampling, err error) { + result = &v1alpha1.PacketSampling{} + err = c.client.Put(). + Resource("packetsamplings"). + Name(packetSampling.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(packetSampling). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *packetSamplings) UpdateStatus(ctx context.Context, packetSampling *v1alpha1.PacketSampling, opts v1.UpdateOptions) (result *v1alpha1.PacketSampling, err error) { + result = &v1alpha1.PacketSampling{} + err = c.client.Put(). + Resource("packetsamplings"). + Name(packetSampling.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(packetSampling). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the packetSampling and deletes it. Returns an error if one occurs. +func (c *packetSamplings) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Resource("packetsamplings"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *packetSamplings) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("packetsamplings"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched packetSampling. +func (c *packetSamplings) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.PacketSampling, err error) { + result = &v1alpha1.PacketSampling{} + err = c.client.Patch(pt). + Resource("packetsamplings"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/crd/v1alpha1/packetsampling.go b/pkg/client/informers/externalversions/crd/v1alpha1/packetsampling.go new file mode 100644 index 00000000000..fa1c7277659 --- /dev/null +++ b/pkg/client/informers/externalversions/crd/v1alpha1/packetsampling.go @@ -0,0 +1,87 @@ +// Copyright 2024 Antrea Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + crdv1alpha1 "antrea.io/antrea/pkg/apis/crd/v1alpha1" + versioned "antrea.io/antrea/pkg/client/clientset/versioned" + internalinterfaces "antrea.io/antrea/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "antrea.io/antrea/pkg/client/listers/crd/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// PacketSamplingInformer provides access to a shared informer and lister for +// PacketSamplings. +type PacketSamplingInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.PacketSamplingLister +} + +type packetSamplingInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewPacketSamplingInformer constructs a new informer for PacketSampling type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewPacketSamplingInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredPacketSamplingInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredPacketSamplingInformer constructs a new informer for PacketSampling type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredPacketSamplingInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdV1alpha1().PacketSamplings().List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CrdV1alpha1().PacketSamplings().Watch(context.TODO(), options) + }, + }, + &crdv1alpha1.PacketSampling{}, + resyncPeriod, + indexers, + ) +} + +func (f *packetSamplingInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredPacketSamplingInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *packetSamplingInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&crdv1alpha1.PacketSampling{}, f.defaultInformer) +} + +func (f *packetSamplingInformer) Lister() v1alpha1.PacketSamplingLister { + return v1alpha1.NewPacketSamplingLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/listers/crd/v1alpha1/packetsampling.go b/pkg/client/listers/crd/v1alpha1/packetsampling.go new file mode 100644 index 00000000000..a1cef4bd250 --- /dev/null +++ b/pkg/client/listers/crd/v1alpha1/packetsampling.go @@ -0,0 +1,66 @@ +// Copyright 2024 Antrea Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "antrea.io/antrea/pkg/apis/crd/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// PacketSamplingLister helps list PacketSamplings. +// All objects returned here must be treated as read-only. +type PacketSamplingLister interface { + // List lists all PacketSamplings in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.PacketSampling, err error) + // Get retrieves the PacketSampling from the index for a given name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.PacketSampling, error) + PacketSamplingListerExpansion +} + +// packetSamplingLister implements the PacketSamplingLister interface. +type packetSamplingLister struct { + indexer cache.Indexer +} + +// NewPacketSamplingLister returns a new PacketSamplingLister. +func NewPacketSamplingLister(indexer cache.Indexer) PacketSamplingLister { + return &packetSamplingLister{indexer: indexer} +} + +// List lists all PacketSamplings in the indexer. +func (s *packetSamplingLister) List(selector labels.Selector) (ret []*v1alpha1.PacketSampling, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.PacketSampling)) + }) + return ret, err +} + +// Get retrieves the PacketSampling from the index for a given name. +func (s *packetSamplingLister) Get(name string) (*v1alpha1.PacketSampling, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("packetsampling"), name) + } + return obj.(*v1alpha1.PacketSampling), nil +} diff --git a/pkg/controller/packetsampling/validate_test.go b/pkg/controller/packetsampling/validate_test.go index 516cc163497..e00486b001f 100644 --- a/pkg/controller/packetsampling/validate_test.go +++ b/pkg/controller/packetsampling/validate_test.go @@ -51,7 +51,7 @@ func TestControllerValidate(t *testing.T) { Pod: "test-pod", }, }, - deniedReason: "PacketSampling ps has invalid type (supported are [FirstNSampling])", + deniedReason: "PacketSampling ps has invalid type , supported type is [FirstNSampling]", }, { name: "FistNSampling config not set", diff --git a/test/e2e/packetsampling_test.go b/test/e2e/packetsampling_test.go index c1349955ca7..03e17e70826 100644 --- a/test/e2e/packetsampling_test.go +++ b/test/e2e/packetsampling_test.go @@ -536,6 +536,9 @@ func runPacketSamplingTest(t *testing.T, data *TestData, tc psTestCase) { tc.skipIfNeeded(t) } + // wait for toolbox + waitForPodIPs(t, data, []PodInfo{{psToolboxPodName, getOSString(), "", data.testNamespace}}) + dstPodName := tc.ps.Spec.Destination.Pod var dstPodIPs *PodIPs if dstPodName != nonExistPodName && dstPodName != "" {