func (s *serviceAccount) limitSecretReferences(serviceAccount *api.ServiceAccount, pod *api.Pod) error { // Ensure all secrets the pod references are allowed by the service account mountableSecrets := util.NewStringSet() for _, s := range serviceAccount.Secrets { mountableSecrets.Insert(s.Name) } for _, volume := range pod.Spec.Volumes { source := volume.VolumeSource if source.Secret == nil { continue } secretName := source.Secret.SecretName if !mountableSecrets.Has(secretName) { return fmt.Errorf("Volume with secret.secretName=\"%s\" is not allowed because service account %s does not reference that secret", secretName, serviceAccount.Name) } } // limit pull secret references as well pullSecrets := util.NewStringSet() for _, s := range serviceAccount.ImagePullSecrets { pullSecrets.Insert(s.Name) } for i, pullSecretRef := range pod.Spec.ImagePullSecrets { if !pullSecrets.Has(pullSecretRef.Name) { return fmt.Errorf(`imagePullSecrets[%d].name="%s" is not allowed because service account %s does not reference that imagePullSecret`, i, pullSecretRef.Name, serviceAccount.Name) } } return nil }
func TestAdd(t *testing.T) { testCases := []struct { sel Selector key string operator Operator values []string refSelector Selector }{ { LabelSelector{}, "key", InOperator, []string{"value"}, LabelSelector{Requirement{"key", InOperator, util.NewStringSet("value")}}, }, { LabelSelector{Requirement{"key", InOperator, util.NewStringSet("value")}}, "key2", EqualsOperator, []string{"value2"}, LabelSelector{ Requirement{"key", InOperator, util.NewStringSet("value")}, Requirement{"key2", EqualsOperator, util.NewStringSet("value2")}, }, }, } for _, ts := range testCases { ts.sel = ts.sel.Add(ts.key, ts.operator, ts.values) if !reflect.DeepEqual(ts.sel, ts.refSelector) { t.Errorf("Expected %t found %t", ts.refSelector, ts.sel) } } }
// Test public interface func doTestIndex(t *testing.T, indexer Indexer) { mkObj := func(id string, val string) testStoreObject { return testStoreObject{id: id, val: val} } // Test Index expected := map[string]util.StringSet{} expected["b"] = util.NewStringSet("a", "c") expected["f"] = util.NewStringSet("e") expected["h"] = util.NewStringSet("g") indexer.Add(mkObj("a", "b")) indexer.Add(mkObj("c", "b")) indexer.Add(mkObj("e", "f")) indexer.Add(mkObj("g", "h")) { for k, v := range expected { found := util.StringSet{} indexResults, err := indexer.Index("by_val", mkObj("", k)) if err != nil { t.Errorf("Unexpected error %v", err) } for _, item := range indexResults { found.Insert(item.(testStoreObject).id) } items := v.List() if !found.HasAll(items...) { t.Errorf("missing items, index %s, expected %v but found %v", k, items, found.List()) } } } }
func TestToString(t *testing.T) { var req Requirement toStringTests := []struct { In *LabelSelector Out string Valid bool }{ {&LabelSelector{ getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t), getRequirement("y", NotInOperator, util.NewStringSet("jkl"), t), getRequirement("z", ExistsOperator, nil, t)}, "x in (abc,def),y notin (jkl),z", true}, {&LabelSelector{ getRequirement("x", InOperator, util.NewStringSet("abc", "def"), t), req}, // adding empty req for the trailing ',' "x in (abc,def),", false}, {&LabelSelector{ getRequirement("x", NotInOperator, util.NewStringSet("abc"), t), getRequirement("y", InOperator, util.NewStringSet("jkl", "mno"), t), getRequirement("z", NotInOperator, util.NewStringSet(""), t)}, "x notin (abc),y in (jkl,mno),z notin ()", true}, {&LabelSelector{ getRequirement("x", EqualsOperator, util.NewStringSet("abc"), t), getRequirement("y", DoubleEqualsOperator, util.NewStringSet("jkl"), t), getRequirement("z", NotEqualsOperator, util.NewStringSet("a"), t)}, "x=abc,y==jkl,z!=a", true}, } for _, ts := range toStringTests { if out := ts.In.String(); out == "" && ts.Valid { t.Errorf("%+v.String() => '%v' expected no error", ts.In, out) } else if out != ts.Out { t.Errorf("%+v.String() => '%v' want '%v'", ts.In, out, ts.Out) } } }
func (im *realImageManager) detectImages(detected time.Time) error { images, err := im.dockerClient.ListImages(docker.ListImagesOptions{}) if err != nil { return err } containers, err := im.dockerClient.ListContainers(docker.ListContainersOptions{ All: true, }) if err != nil { return err } // Make a set of images in use by containers. imagesInUse := util.NewStringSet() for _, container := range containers { imagesInUse.Insert(container.Image) } // Add new images and record those being used. now := time.Now() currentImages := util.NewStringSet() im.imageRecordsLock.Lock() defer im.imageRecordsLock.Unlock() for _, image := range images { currentImages.Insert(image.ID) // New image, set it as detected now. if _, ok := im.imageRecords[image.ID]; !ok { im.imageRecords[image.ID] = &imageRecord{ detected: detected, } } // Set last used time to now if the image is being used. if isImageUsed(&image, imagesInUse) { im.imageRecords[image.ID].lastUsed = now } im.imageRecords[image.ID].size = image.VirtualSize } // Remove old images from our records. for image := range im.imageRecords { if !currentImages.Has(image) { delete(im.imageRecords, image) } } return nil }
func TestEtcdWatch(t *testing.T) { table := map[string]generic.Matcher{ "single": setMatcher{util.NewStringSet("foo")}, "multi": setMatcher{util.NewStringSet("foo", "bar")}, } for name, m := range table { podA := &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: api.NamespaceDefault, ResourceVersion: "1", }, Spec: api.PodSpec{NodeName: "machine"}, } respWithPodA := &etcd.Response{ Node: &etcd.Node{ Key: "/registry/pods/default/foo", Value: runtime.EncodeOrDie(testapi.Codec(), podA), ModifiedIndex: 1, CreatedIndex: 1, }, Action: "create", } fakeClient, registry := NewTestGenericEtcdRegistry(t) wi, err := registry.WatchPredicate(api.NewContext(), m, "1") if err != nil { t.Errorf("%v: unexpected error: %v", name, err) continue } fakeClient.WaitForWatchCompletion() go func() { fakeClient.WatchResponse <- respWithPodA }() got, open := <-wi.ResultChan() if !open { t.Errorf("%v: unexpected channel close", name) continue } if e, a := podA, got.Object; !api.Semantic.DeepDerivative(e, a) { t.Errorf("%v: difference: %s", name, util.ObjectDiff(e, a)) } } }
func newFakeMirrorClient() *fakeMirrorClient { m := fakeMirrorClient{} m.mirrorPods = util.NewStringSet() m.createCounts = make(map[string]int) m.deleteCounts = make(map[string]int) return &m }
func TestFlushChain(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // Success. func() ([]byte, error) { return []byte{}, nil }, // Failure. func() ([]byte, error) { return nil, &exec.FakeExitError{1} }, }, } fexec := exec.FakeExec{ CommandScript: []exec.FakeCommandAction{ func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, }, } runner := New(&fexec, ProtocolIpv4) // Success. err := runner.FlushChain(TableNAT, Chain("FOOBAR")) if err != nil { t.Errorf("expected success, got %v", err) } if fcmd.CombinedOutputCalls != 1 { t.Errorf("expected 1 CombinedOutput() call, got %d", fcmd.CombinedOutputCalls) } if !util.NewStringSet(fcmd.CombinedOutputLog[0]...).HasAll("iptables", "-t", "nat", "-F", "FOOBAR") { t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) } // Failure. err = runner.FlushChain(TableNAT, Chain("FOOBAR")) if err == nil { t.Errorf("expected failure") } }
func TestDeleteRuleNew(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // iptables version check func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, // Success on the first call. func() ([]byte, error) { return []byte{}, nil }, // Success on the second call. func() ([]byte, error) { return []byte{}, nil }, }, } fexec := exec.FakeExec{ CommandScript: []exec.FakeCommandAction{ // iptables version check func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, // The second Command() call is checking the rule. Success of that means delete it. func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, }, } runner := New(&fexec, ProtocolIpv4) err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123") if err != nil { t.Errorf("expected success, got %v", err) } if fcmd.CombinedOutputCalls != 3 { t.Errorf("expected 3 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls) } if !util.NewStringSet(fcmd.CombinedOutputLog[2]...).HasAll("iptables", "-t", "nat", "-D", "OUTPUT", "abc", "123") { t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1]) } }
func TestDeleteRuleAlreadyExists(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // iptables version check func() ([]byte, error) { return []byte("iptables v1.9.22"), nil }, // Status 1 on the first call. func() ([]byte, error) { return nil, &exec.FakeExitError{1} }, }, } fexec := exec.FakeExec{ CommandScript: []exec.FakeCommandAction{ // iptables version check func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, // The second Command() call is checking the rule. Failure of that exec means "does not exist". func(cmd string, args ...string) exec.Cmd { return exec.InitFakeCmd(&fcmd, cmd, args...) }, }, } runner := New(&fexec, ProtocolIpv4) err := runner.DeleteRule(TableNAT, ChainOutput, "abc", "123") if err != nil { t.Errorf("expected success, got %v", err) } if fcmd.CombinedOutputCalls != 2 { t.Errorf("expected 2 CombinedOutput() call, got %d", fcmd.CombinedOutputCalls) } if !util.NewStringSet(fcmd.CombinedOutputLog[1]...).HasAll("iptables", "-t", "nat", "-C", "OUTPUT", "abc", "123") { t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0]) } }
func describeService(service *api.Service, endpoints *api.Endpoints, events *api.EventList) (string, error) { if endpoints == nil { endpoints = &api.Endpoints{} } return tabbedString(func(out io.Writer) error { fmt.Fprintf(out, "Name:\t%s\n", service.Name) fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(service.Labels)) fmt.Fprintf(out, "Selector:\t%s\n", formatLabels(service.Spec.Selector)) fmt.Fprintf(out, "Type:\t%s\n", service.Spec.Type) fmt.Fprintf(out, "IP:\t%s\n", service.Spec.ClusterIP) if len(service.Status.LoadBalancer.Ingress) > 0 { list := buildIngressString(service.Status.LoadBalancer.Ingress) fmt.Fprintf(out, "LoadBalancer Ingress:\t%s\n", list) } for i := range service.Spec.Ports { sp := &service.Spec.Ports[i] name := sp.Name if name == "" { name = "<unnamed>" } fmt.Fprintf(out, "Port:\t%s\t%d/%s\n", name, sp.Port, sp.Protocol) if sp.NodePort != 0 { fmt.Fprintf(out, "NodePort:\t%s\t%d/%s\n", name, sp.NodePort, sp.Protocol) } fmt.Fprintf(out, "Endpoints:\t%s\n", formatEndpoints(endpoints, util.NewStringSet(sp.Name))) } fmt.Fprintf(out, "Session Affinity:\t%s\n", service.Spec.SessionAffinity) if events != nil { DescribeEvents(events, out) } return nil }) }
func TestSyncNamespaceThatIsActive(t *testing.T) { mockClient := &testclient.Fake{} testNamespace := api.Namespace{ ObjectMeta: api.ObjectMeta{ Name: "test", ResourceVersion: "1", }, Spec: api.NamespaceSpec{ Finalizers: []api.FinalizerName{"qingyuan"}, }, Status: api.NamespaceStatus{ Phase: api.NamespaceActive, }, } err := syncNamespace(mockClient, testNamespace) if err != nil { t.Errorf("Unexpected error when synching namespace %v", err) } actionSet := util.NewStringSet() for i := range mockClient.Actions { actionSet.Insert(mockClient.Actions[i].Action) } if len(actionSet) != 0 { t.Errorf("Expected no action from controller, but got: %v", actionSet) } }
func getSecretReferences(serviceAccount *api.ServiceAccount) util.StringSet { references := util.NewStringSet() for _, secret := range serviceAccount.Secrets { references.Insert(secret.Name) } return references }
func TestTTLExpirationBasic(t *testing.T) { testObj := testStoreObject{id: "foo", val: "bar"} deleteChan := make(chan string) ttlStore := NewFakeExpirationStore( testStoreKeyFunc, deleteChan, &FakeExpirationPolicy{ NeverExpire: util.NewStringSet(), RetrieveKeyFunc: func(obj interface{}) (string, error) { return obj.(*timestampedEntry).obj.(testStoreObject).id, nil }, }, util.RealClock{}, ) err := ttlStore.Add(testObj) if err != nil { t.Errorf("Unable to add obj %#v", testObj) } item, exists, err := ttlStore.Get(testObj) if err != nil { t.Errorf("Failed to get from store, %v", err) } if exists || item != nil { t.Errorf("Got unexpected item %#v", item) } key, _ := testStoreKeyFunc(testObj) select { case delKey := <-deleteChan: if delKey != key { t.Errorf("Unexpected delete for key %s", key) } case <-time.After(time.Millisecond * 100): t.Errorf("Unexpected timeout waiting on delete") } close(deleteChan) }
// parseIdentifiersList parses a (possibly empty) list of // of comma separated (possibly empty) identifiers func (p *Parser) parseIdentifiersList() (util.StringSet, error) { s := util.NewStringSet() for { tok, lit := p.consume(Values) switch tok { case IdentifierToken: s.Insert(lit) tok2, lit2 := p.lookahead(Values) switch tok2 { case CommaToken: continue case ClosedParToken: return s, nil default: return nil, fmt.Errorf("found '%s', expected: ',' or ')'", lit2) } case CommaToken: // handled here since we can have "(," if s.Len() == 0 { s.Insert("") // to handle (, } tok2, _ := p.lookahead(Values) if tok2 == ClosedParToken { s.Insert("") // to handle ,) Double "" removed by StringSet return s, nil } if tok2 == CommaToken { p.consume(Values) s.Insert("") // to handle ,, Double "" removed by StringSet } default: // it can be operator return s, fmt.Errorf("found '%s', expected: ',', or identifier", lit) } } }
// implementation of the error interface func (f *FitError) Error() string { predicates := util.NewStringSet() for node, predicateList := range f.FailedPredicates { predicates = predicates.Union(predicateList) glog.Infof("failed to find fit for pod %v on node %s: %s", f.Pod.Name, node, strings.Join(predicateList.List(), ",")) } return fmt.Sprintf("For each of these fitness predicates, pod %v failed on at least one node: %v.", f.Pod.Name, strings.Join(predicates.List(), ",")) }
func TestTTLList(t *testing.T) { testObjs := []testStoreObject{ {id: "foo", val: "bar"}, {id: "foo1", val: "bar1"}, {id: "foo2", val: "bar2"}, } expireKeys := util.NewStringSet(testObjs[0].id, testObjs[2].id) deleteChan := make(chan string) defer close(deleteChan) ttlStore := NewFakeExpirationStore( testStoreKeyFunc, deleteChan, &FakeExpirationPolicy{ NeverExpire: util.NewStringSet(testObjs[1].id), RetrieveKeyFunc: func(obj interface{}) (string, error) { return obj.(*timestampedEntry).obj.(testStoreObject).id, nil }, }, util.RealClock{}, ) for _, obj := range testObjs { err := ttlStore.Add(obj) if err != nil { t.Errorf("Unable to add obj %#v", obj) } } listObjs := ttlStore.List() if len(listObjs) != 1 || !reflect.DeepEqual(listObjs[0], testObjs[1]) { t.Errorf("List returned unexpected results %#v", listObjs) } // Make sure all our deletes come through in an acceptable rate (1/100ms) for expireKeys.Len() != 0 { select { case delKey := <-deleteChan: if !expireKeys.Has(delKey) { t.Errorf("Unexpected delete for key %s", delKey) } expireKeys.Delete(delKey) case <-time.After(time.Millisecond * 100): t.Errorf("Unexpected timeout waiting on delete") return } } }
func TestEvictNode(t *testing.T) { evictor := NewPodEvictor(util.NewFakeRateLimiter()) evictor.AddNodeToEvict("first") evictor.AddNodeToEvict("second") evictor.AddNodeToEvict("third") evictor.RemoveNodeToEvict("second") deletedMap := util.NewStringSet() evictor.TryEvict(func(nodeName string) { deletedMap.Insert(nodeName) }) setPattern := util.NewStringSet("first", "third") if len(deletedMap) != len(setPattern) { t.Fatalf("Map %v should have length %d", evictor.queue.set, len(setPattern)) } if !CheckSetEq(setPattern, deletedMap) { t.Errorf("Invalid map. Got %v, expected %v", deletedMap, setPattern) } }
// Creates new PodEvictor which will use given RateLimiter to oversee eviction. func NewPodEvictor(deletingPodsRateLimiter util.RateLimiter) *PodEvictor { return &PodEvictor{ queue: UniqueQueue{ queue: make([]string, 0), set: util.NewStringSet(), }, deletingPodsRateLimiter: deletingPodsRateLimiter, } }
// parseExactValue parses the only value for exact match style func (p *Parser) parseExactValue() (util.StringSet, error) { s := util.NewStringSet() tok, lit := p.consume(Values) if tok == IdentifierToken { s.Insert(lit) return s, nil } return nil, fmt.Errorf("found '%s', expected: identifier", lit) }
// NewHandler creates a new base handler that handles the passed // in operations func NewHandler(ops ...Operation) *Handler { operations := util.NewStringSet() for _, op := range ops { operations.Insert(string(op)) } return &Handler{ operations: operations, } }
// Add adds a requirement to the selector. It copies the current selector returning a new one func (lsel LabelSelector) Add(key string, operator Operator, values []string) Selector { var reqs []Requirement for _, item := range lsel { reqs = append(reqs, item) } if r, err := NewRequirement(key, operator, util.NewStringSet(values...)); err == nil { reqs = append(reqs, *r) } return LabelSelector(reqs) }
func TestActivePodFiltering(t *testing.T) { // This rc is not needed by the test, only the newPodList to give the pods labels/a namespace. rc := newReplicationController(0) podList := newPodList(nil, 5, api.PodRunning, rc) podList.Items[0].Status.Phase = api.PodSucceeded podList.Items[1].Status.Phase = api.PodFailed expectedNames := util.NewStringSet() for _, pod := range podList.Items[2:] { expectedNames.Insert(pod.Name) } got := filterActivePods(podList.Items) gotNames := util.NewStringSet() for _, pod := range got { gotNames.Insert(pod.Name) } if expectedNames.Difference(gotNames).Len() != 0 || gotNames.Difference(expectedNames).Len() != 0 { t.Errorf("expected %v, got %v", expectedNames.List(), gotNames.List()) } }
// delete the slave-offer mappings for slaveId, returns the IDs of the offers that were unmapped func (self *slaveStorage) deleteSlave(slaveId string) util.StringSet { offerIds := util.NewStringSet() self.Lock() defer self.Unlock() for oid, sid := range self.index { if sid == slaveId { offerIds.Insert(oid) delete(self.index, oid) } } return offerIds }
func TestRequirementLabelSelectorMatching(t *testing.T) { var req Requirement labelSelectorMatchingTests := []struct { Set Set Sel *LabelSelector Match bool }{ {Set{"x": "foo", "y": "baz"}, &LabelSelector{ req, }, false}, {Set{"x": "foo", "y": "baz"}, &LabelSelector{ getRequirement("x", InOperator, util.NewStringSet("foo"), t), getRequirement("y", NotInOperator, util.NewStringSet("alpha"), t), }, true}, {Set{"x": "foo", "y": "baz"}, &LabelSelector{ getRequirement("x", InOperator, util.NewStringSet("foo"), t), getRequirement("y", InOperator, util.NewStringSet("alpha"), t), }, false}, {Set{"y": ""}, &LabelSelector{ getRequirement("x", NotInOperator, util.NewStringSet(""), t), getRequirement("y", ExistsOperator, nil, t), }, true}, {Set{"y": "baz"}, &LabelSelector{ getRequirement("x", InOperator, util.NewStringSet(""), t), }, false}, } for _, lsm := range labelSelectorMatchingTests { if match := lsm.Sel.Matches(lsm.Set); match != lsm.Match { t.Errorf("%+v.Matches(%#v) => %v, want %v", lsm.Sel, lsm.Set, match, lsm.Match) } } }
// Executes the rule check without using the "-C" flag, instead parsing iptables-save. // Present for compatibility with <1.4.11 versions of iptables. This is full // of hack and half-measures. We should nix this ASAP. func (runner *runner) checkRuleWithoutCheck(table Table, chain Chain, args ...string) (bool, error) { glog.V(1).Infof("running iptables-save -t %s", string(table)) out, err := runner.exec.Command("iptables-save", "-t", string(table)).CombinedOutput() if err != nil { return false, fmt.Errorf("error checking rule: %v", err) } // Sadly, iptables has inconsistent quoting rules for comments. // Just unquote any arg that is wrapped in quotes. argsCopy := make([]string, len(args)) copy(argsCopy, args) for i := range argsCopy { unquote(&argsCopy[i]) } argset := util.NewStringSet(argsCopy...) for _, line := range strings.Split(string(out), "\n") { var fields = strings.Fields(line) // Check that this is a rule for the correct chain, and that it has // the correct number of argument (+2 for "-A <chain name>") if !strings.HasPrefix(line, fmt.Sprintf("-A %s", string(chain))) || len(fields) != len(args)+2 { continue } // Sadly, iptables has inconsistent quoting rules for comments. // Just unquote any arg that is wrapped in quotes. for i := range fields { unquote(&fields[i]) } // TODO: This misses reorderings e.g. "-x foo ! -y bar" will match "! -x foo -y bar" if util.NewStringSet(fields...).IsSuperset(argset) { return true, nil } glog.V(5).Infof("DBG: fields is not a superset of args: fields=%v args=%v", fields, args) } return false, nil }
func TestSyncNamespaceThatIsTerminating(t *testing.T) { mockClient := &testclient.Fake{} now := util.Now() testNamespace := api.Namespace{ ObjectMeta: api.ObjectMeta{ Name: "test", ResourceVersion: "1", DeletionTimestamp: &now, }, Spec: api.NamespaceSpec{ Finalizers: []api.FinalizerName{"qingyuan"}, }, Status: api.NamespaceStatus{ Phase: api.NamespaceTerminating, }, } err := syncNamespace(mockClient, testNamespace) if err != nil { t.Errorf("Unexpected error when synching namespace %v", err) } // TODO: Reuse the constants for all these strings from testclient expectedActionSet := util.NewStringSet( testclient.ListControllerAction, "list-services", "list-pods", "list-resourceQuotas", "list-secrets", "list-limitRanges", "list-events", "finalize-namespace", "delete-namespace") actionSet := util.NewStringSet() for i := range mockClient.Actions { actionSet.Insert(mockClient.Actions[i].Action) } if !actionSet.HasAll(expectedActionSet.List()...) { t.Errorf("Expected actions: %v, but got: %v", expectedActionSet, actionSet) } }
// Creates a scheduler from the configuration file func (f *ConfigFactory) CreateFromConfig(policy schedulerapi.Policy) (*scheduler.Config, error) { glog.V(2).Infof("creating scheduler from configuration: %v", policy) // validate the policy configuration if err := validation.ValidatePolicy(policy); err != nil { return nil, err } predicateKeys := util.NewStringSet() for _, predicate := range policy.Predicates { glog.V(2).Infof("Registering predicate: %s", predicate.Name) predicateKeys.Insert(RegisterCustomFitPredicate(predicate)) } priorityKeys := util.NewStringSet() for _, priority := range policy.Priorities { glog.V(2).Infof("Registering priority: %s", priority.Name) priorityKeys.Insert(RegisterCustomPriorityFunction(priority)) } return f.CreateFromKeys(predicateKeys, priorityKeys) }
// roundTripSame verifies the same source object is tested in all API versions. func roundTripSame(t *testing.T, item runtime.Object, except ...string) { set := util.NewStringSet(except...) seed := rand.Int63() fuzzInternalObject(t, "", item, seed) if !set.Has("v1beta3") { fuzzInternalObject(t, "v1beta3", item, seed) roundTrip(t, v1beta3.Codec, item) } if !set.Has("v1") { fuzzInternalObject(t, "v1", item, seed) roundTrip(t, v1.Codec, item) } }
func TestUpdatePods(t *testing.T) { fakeWatch := watch.NewFake() client := &testclient.Fake{Watch: fakeWatch} manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady received := make(chan string) manager.syncHandler = func(key string) error { obj, exists, err := manager.controllerStore.Store.GetByKey(key) if !exists || err != nil { t.Errorf("Expected to find controller under key %v", key) } received <- obj.(*api.ReplicationController).Name return nil } stopCh := make(chan struct{}) defer close(stopCh) go util.Until(manager.worker, 10*time.Millisecond, stopCh) // Put 2 rcs and one pod into the controller's stores testControllerSpec1 := newReplicationController(1) manager.controllerStore.Store.Add(testControllerSpec1) testControllerSpec2 := *testControllerSpec1 testControllerSpec2.Spec.Selector = map[string]string{"bar": "foo"} testControllerSpec2.Name = "barfoo" manager.controllerStore.Store.Add(&testControllerSpec2) // Put one pod in the podStore pod1 := newPodList(manager.podStore.Store, 1, api.PodRunning, testControllerSpec1).Items[0] pod2 := pod1 pod2.Labels = testControllerSpec2.Spec.Selector // Send an update of the same pod with modified labels, and confirm we get a sync request for // both controllers manager.updatePod(&pod1, &pod2) expected := util.NewStringSet(testControllerSpec1.Name, testControllerSpec2.Name) for _, name := range expected.List() { t.Logf("Expecting update for %+v", name) select { case got := <-received: if !expected.Has(got) { t.Errorf("Expected keys %#v got %v", expected, got) } case <-time.After(controllerTimeout): t.Errorf("Expected update notifications for controllers within 100ms each") } } }