func TestAllocate(t *testing.T) { ranger, _ := mcs.NewRange("s0:", 5, 2) r := New(ranger, func(max int, rangeSpec string) allocator.Interface { return allocator.NewContiguousAllocationMap(max, rangeSpec) }) if f := r.Free(); f != 10 { t.Errorf("unexpected free %d", f) } found := sets.NewString() count := 0 for r.Free() > 0 { label, err := r.AllocateNext() if err != nil { t.Fatalf("error @ %d: %v", count, err) } count++ if !ranger.Contains(label) { t.Fatalf("allocated %s which is outside of %s", label, ranger) } if found.Has(label.String()) { t.Fatalf("allocated %s twice @ %d", label, count) } found.Insert(label.String()) } if _, err := r.AllocateNext(); err != ErrFull { t.Fatal(err) } released, _ := ranger.LabelAt(3) if err := r.Release(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("unexpected free %d", f) } label, err := r.AllocateNext() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(released, label) { t.Errorf("unexpected %s : %s", label, released) } if err := r.Release(released); err != nil { t.Fatal(err) } badLabel, _ := ranger.LabelAt(30) if err := r.Allocate(badLabel); err != ErrNotInRange { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("unexpected free %d", f) } if err := r.Allocate(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 0 { t.Errorf("unexpected free %d", f) } }
// RunSecurityAllocationController starts the security allocation controller process. func (c *MasterConfig) RunSecurityAllocationController() { alloc := c.Options.ProjectConfig.SecurityAllocator if alloc == nil { glog.V(3).Infof("Security allocator is disabled - no UIDs assigned to projects") return } // TODO: move range initialization to run_config uidRange, err := uid.ParseRange(alloc.UIDAllocatorRange) if err != nil { glog.Fatalf("Unable to describe UID range: %v", err) } opts, err := c.RESTOptionsGetter.GetRESTOptions(unversioned.GroupResource{Resource: "securityuidranges"}) if err != nil { glog.Fatalf("Unable to load storage options for security UID ranges") } var etcdAlloc *etcdallocator.Etcd uidAllocator := uidallocator.New(uidRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewContiguousAllocationMap(max, rangeSpec) etcdAlloc = etcdallocator.NewEtcd(mem, "/ranges/uids", kapi.Resource("uidallocation"), opts.StorageConfig) return etcdAlloc }) mcsRange, err := mcs.ParseRange(alloc.MCSAllocatorRange) if err != nil { glog.Fatalf("Unable to describe MCS category range: %v", err) } kclient := c.SecurityAllocationControllerClient() repair := securitycontroller.NewRepair(time.Minute, kclient.Namespaces(), uidRange, etcdAlloc) if err := repair.RunOnce(); err != nil { // TODO: v scary, may need to use direct etcd calls? // If the security controller fails during RunOnce it could mean a // couple of things: // 1. an unexpected etcd error occurred getting an allocator or the namespaces // 2. the allocation blocks were full - would result in an admission controller that is unable // to create the strategies correctly which would likely mean that the cluster // would not admit pods the the majority of users. // 3. an unexpected error persisting an allocation for a namespace has occurred - same as above // In all cases we do not want to continue normal operations, this should be fatal. glog.Fatalf("Unable to initialize namespaces: %v", err) } factory := securitycontroller.AllocationFactory{ UIDAllocator: uidAllocator, MCSAllocator: securitycontroller.DefaultMCSAllocation(uidRange, mcsRange, alloc.MCSLabelsPerProject), Client: kclient.Namespaces(), // TODO: reuse namespace cache } controller := factory.Create() controller.Run() }
// RunSecurityAllocationController starts the security allocation controller process. func (c *MasterConfig) RunSecurityAllocationController() { alloc := c.Options.ProjectConfig.SecurityAllocator if alloc == nil { glog.V(3).Infof("Security allocator is disabled - no UIDs assigned to projects") return } // TODO: move range initialization to run_config uidRange, err := uid.ParseRange(alloc.UIDAllocatorRange) if err != nil { glog.Fatalf("Unable to describe UID range: %v", err) } var etcdAlloc *etcdallocator.Etcd uidAllocator := uidallocator.New(uidRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewContiguousAllocationMap(max, rangeSpec) etcdAlloc = etcdallocator.NewEtcd(mem, "/ranges/uids", "uidallocation", c.EtcdHelper) return etcdAlloc }) mcsRange, err := mcs.ParseRange(alloc.MCSAllocatorRange) if err != nil { glog.Fatalf("Unable to describe MCS category range: %v", err) } kclient := c.SecurityAllocationControllerClient() repair := securitycontroller.NewRepair(time.Minute, kclient.Namespaces(), uidRange, etcdAlloc) if err := repair.RunOnce(); err != nil { // TODO: v scary, may need to use direct etcd calls? glog.Fatalf("Unable to initialize namespaces: %v", err) } factory := securitycontroller.AllocationFactory{ UIDAllocator: uidAllocator, MCSAllocator: securitycontroller.DefaultMCSAllocation(uidRange, mcsRange, alloc.MCSLabelsPerProject), Client: kclient.Namespaces(), // TODO: reuse namespace cache } controller := factory.Create() controller.Run() }
// NewInMemory creates an in-memory Allocator func NewInMemory(r *uid.Range) *Allocator { factory := func(max int, rangeSpec string) allocator.Interface { return allocator.NewContiguousAllocationMap(max, rangeSpec) } return New(r, factory) }
func TestAllocate(t *testing.T) { ranger, _ := uid.NewRange(0, 9, 2) r := New(ranger, func(max int, rangeSpec string) allocator.Interface { return allocator.NewContiguousAllocationMap(max, rangeSpec) }) if f := r.Free(); f != 5 { t.Errorf("unexpected free %d", f) } found := sets.NewString() count := 0 for r.Free() > 0 { block, err := r.AllocateNext() if err != nil { t.Fatalf("error @ %d: %v", count, err) } count++ if !ranger.Contains(block) { t.Fatalf("allocated %s which is outside of %s", block, ranger) } if found.Has(block.String()) { t.Fatalf("allocated %s twice @ %d", block, count) } found.Insert(block.String()) } if _, err := r.AllocateNext(); err != ErrFull { t.Fatal(err) } released := uid.Block{Start: 2, End: 3} if err := r.Release(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("unexpected free %d", f) } block, err := r.AllocateNext() if err != nil { t.Fatal(err) } if released != block { t.Errorf("unexpected %s : %s", block, released) } if err := r.Release(released); err != nil { t.Fatal(err) } if err := r.Allocate(uid.Block{Start: 11, End: 11}); err != ErrNotInRange { t.Fatal(err) } if err := r.Allocate(uid.Block{Start: 8, End: 11}); err != ErrNotInRange { t.Fatal(err) } if f := r.Free(); f != 1 { t.Errorf("unexpected free %d", f) } if err := r.Allocate(released); err != nil { t.Fatal(err) } if f := r.Free(); f != 0 { t.Errorf("unexpected free %d", f) } }