diff --git a/pkg/util/ipset/testing/fake.go b/pkg/util/ipset/testing/fake.go index aedf3d21b3..2a58bdd399 100644 --- a/pkg/util/ipset/testing/fake.go +++ b/pkg/util/ipset/testing/fake.go @@ -17,67 +17,127 @@ limitations under the License. package testing import ( + "fmt" + + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/util/ipset" ) // FakeIPSet is a no-op implementation of ipset Interface type FakeIPSet struct { - Lines []byte + // version of ipset util + Version string + // The key of Sets map is the ip set name + Sets map[string]*ipset.IPSet + // The key of Entries map is the ip set name where the entries exists + Entries map[string]sets.String } -// NewFake create a new fake ipset interface. -func NewFake() *FakeIPSet { - return &FakeIPSet{} +// NewFake create a new fake ipset interface - it initialize the FakeIPSet. +func NewFake(version string) *FakeIPSet { + return &FakeIPSet{ + Version: version, + Sets: make(map[string]*ipset.IPSet), + Entries: make(map[string]sets.String), + } } // GetVersion is part of interface. -func (*FakeIPSet) GetVersion() (string, error) { - return "0.0", nil +func (f *FakeIPSet) GetVersion() (string, error) { + return f.Version, nil } -// FlushSet is part of interface. -func (*FakeIPSet) FlushSet(set string) error { +// FlushSet is part of interface. It deletes all entries from a named set but keeps the set itself. +func (f *FakeIPSet) FlushSet(set string) error { + if f.Entries == nil { + return fmt.Errorf("entries map can't be nil") + } + + // delete all entry elements + for true { + if _, has := f.Entries[set].PopAny(); has { + continue + } + break + } return nil } -// DestroySet is part of interface. -func (*FakeIPSet) DestroySet(set string) error { +// DestroySet is part of interface. It deletes both the entries and the set itself. +func (f *FakeIPSet) DestroySet(set string) error { + delete(f.Sets, set) + delete(f.Entries, set) return nil } // DestroyAllSets is part of interface. -func (*FakeIPSet) DestroyAllSets() error { +func (f *FakeIPSet) DestroyAllSets() error { + f.Sets = nil + f.Entries = nil return nil } // CreateSet is part of interface. -func (*FakeIPSet) CreateSet(set *ipset.IPSet, ignoreExistErr bool) error { +func (f *FakeIPSet) CreateSet(set *ipset.IPSet, ignoreExistErr bool) error { + if f.Sets[set.Name] != nil { + if !ignoreExistErr { + // already exists + return fmt.Errorf("Set cannot be created: set with the same name already exists") + } + return nil + } + f.Sets[set.Name] = set + // initialize entry map + f.Entries[set.Name] = sets.NewString() return nil } // AddEntry is part of interface. -func (*FakeIPSet) AddEntry(entry string, set string, ignoreExistErr bool) error { +func (f *FakeIPSet) AddEntry(entry string, set string, ignoreExistErr bool) error { + if f.Entries[set].Has(entry) { + if !ignoreExistErr { + // already exists + return fmt.Errorf("Element cannot be added to the set: it's already added") + } + return nil + } + f.Entries[set].Insert(entry) return nil } // DelEntry is part of interface. -func (*FakeIPSet) DelEntry(entry string, set string) error { +func (f *FakeIPSet) DelEntry(entry string, set string) error { + if f.Entries == nil { + return fmt.Errorf("entries map can't be nil") + } + f.Entries[set].Delete(entry) return nil } // TestEntry is part of interface. -func (*FakeIPSet) TestEntry(entry string, set string) (bool, error) { - return true, nil +func (f *FakeIPSet) TestEntry(entry string, set string) (bool, error) { + if f.Entries == nil { + return false, fmt.Errorf("entries map can't be nil") + } + found := f.Entries[set].Has(entry) + return found, nil } // ListEntries is part of interface. -func (*FakeIPSet) ListEntries(set string) ([]string, error) { - return nil, nil +func (f *FakeIPSet) ListEntries(set string) ([]string, error) { + if f.Entries == nil { + return nil, fmt.Errorf("entries map can't be nil") + } + return f.Entries[set].UnsortedList(), nil } // ListSets is part of interface. -func (*FakeIPSet) ListSets() ([]string, error) { - return nil, nil +func (f *FakeIPSet) ListSets() ([]string, error) { + res := []string{} + for set := range f.Sets { + res = append(res, set) + } + return res, nil } var _ = ipset.Interface(&FakeIPSet{}) diff --git a/pkg/util/ipset/testing/fake_test.go b/pkg/util/ipset/testing/fake_test.go new file mode 100644 index 0000000000..2128395cf8 --- /dev/null +++ b/pkg/util/ipset/testing/fake_test.go @@ -0,0 +1,152 @@ +/* +Copyright 2017 The Kubernetes 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. +*/ + +package testing + +import ( + "testing" + + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/kubernetes/pkg/util/ipset" +) + +const testVersion = "v6.19" + +func TestSetEntry(t *testing.T) { + fake := NewFake(testVersion) + version, err := fake.GetVersion() + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if version != testVersion { + t.Errorf("Unexpected version mismatch, expected: %s, got: %s", testVersion, version) + } + // create a set + set := &ipset.IPSet{ + Name: "foo", + SetType: ipset.HashIPPort, + HashFamily: ipset.ProtocolFamilyIPV4, + } + if err := fake.CreateSet(set, true); err != nil { + t.Errorf("Unexpected error: %v", err) + } + + // add two entries + fake.AddEntry("192.168.1.1,tcp:8080", set.Name, true) + fake.AddEntry("192.168.1.2,tcp:8081", set.Name, true) + entries, err := fake.ListEntries(set.Name) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if len(entries) != 2 { + t.Errorf("Expected 2 entries, got %d", len(entries)) + } + expectedEntries := sets.NewString("192.168.1.1,tcp:8080", "192.168.1.2,tcp:8081") + if !expectedEntries.Equal(sets.NewString(entries...)) { + t.Errorf("Unexpected entries mismatch, expected: %v, got: %v", expectedEntries, entries) + } + + // test entries + found, err := fake.TestEntry("192.168.1.1,tcp:8080", set.Name) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if !found { + t.Errorf("Unexpected entry 192.168.1.1,tcp:8080 not found") + } + + found, err = fake.TestEntry("192.168.1.2,tcp:8081", set.Name) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if !found { + t.Errorf("Unexpected entry 192.168.1.2,tcp:8081 not found") + } + + // delete entry from a given set + if err := fake.DelEntry("192.168.1.1,tcp:8080", set.Name); err != nil { + t.Errorf("Unexpected error: %v", err) + } + entries, err = fake.ListEntries(set.Name) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if len(entries) != 1 { + t.Errorf("Expected 1 entries, got %d", len(entries)) + } + expectedEntries = sets.NewString("192.168.1.2,tcp:8081") + if !expectedEntries.Equal(sets.NewString(entries...)) { + t.Errorf("Unexpected entries mismatch, expected: %v, got: %v", expectedEntries, entries) + } + + // Flush set + if err := fake.FlushSet(set.Name); err != nil { + t.Errorf("Unexpected error: %v", err) + } + entries, err = fake.ListEntries(set.Name) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if len(entries) != 0 { + t.Errorf("Expected 0 entries, got %d, entries: %v", len(entries), entries) + } + + // create another set + set2 := &ipset.IPSet{ + Name: "bar", + SetType: ipset.HashIPPortIP, + HashFamily: ipset.ProtocolFamilyIPV6, + } + if err := fake.CreateSet(set2, true); err != nil { + t.Errorf("Unexpected error: %v", err) + } + + setList, err := fake.ListSets() + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if len(setList) != 2 { + t.Errorf("Expected 2 sets, got %d", len(setList)) + } + expectedSets := sets.NewString("foo", "bar") + if !expectedSets.Equal(sets.NewString(setList...)) { + t.Errorf("Unexpected sets mismatch, expected: %v, got: %v", expectedSets, setList) + } + + // Destroy a given set + if err := fake.DestroySet(set.Name); err != nil { + t.Errorf("Unexpected error: %v", err) + } + if fake.Sets[set.Name] != nil { + t.Errorf("Unexpected set: %v", fake.Sets[set.Name]) + } + if fake.Entries[set.Name] != nil { + t.Errorf("Unexpected entries: %v", fake.Entries[set.Name]) + } + + // Destroy all sets + if err := fake.DestroyAllSets(); err != nil { + t.Errorf("Unexpected error: %v", err) + } + if len(fake.Sets) != 0 { + t.Errorf("Expected 0 sets, got %d, sets: %v", len(fake.Sets), fake.Sets) + } + if len(fake.Entries) != 0 { + t.Errorf("Expected 0 entries, got %d, entries: %v", len(fake.Entries), fake.Entries) + } +} + +// TODO: Test ignoreExistErr=false