func TestStore(t *testing.T) { storage, server, backing, config := newStorage(t) defer server.Terminate(t) if err := storage.storage.Create(context.TODO(), key(), validNewRangeAllocation(), nil, 0); err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := storage.Allocate(2); err != nil { t.Fatal(err) } ok, err := backing.Allocate(2) if err != nil { t.Fatal(err) } if ok { t.Fatal("Expected backing allocation to fail") } if ok, err := storage.Allocate(2); ok || err != nil { t.Fatal("Expected allocation to fail") } other := allocator.NewAllocationMap(100, "rangeSpecValue") allocation := &api.RangeAllocation{} if err := storage.storage.Get(context.TODO(), key(), "", allocation, false); err != nil { t.Fatal(err) } if allocation.Range != "rangeSpecValue" { t.Errorf("unexpected stored Range: %s", allocation.Range) } if err := other.Restore("rangeSpecValue", allocation.Data); err != nil { t.Fatal(err) } if !other.Has(2) { t.Fatalf("could not restore allocated IP: %#v", other) } other = allocator.NewAllocationMap(100, "rangeSpecValue") otherStorage := NewEtcd(other, "/ranges/serviceips", api.Resource("serviceipallocations"), config) if ok, err := otherStorage.Allocate(2); ok || err != nil { t.Fatal(err) } }
// NewIngressIPController creates a new IngressIPController. // TODO this should accept a shared informer func NewIngressIPController(kc kclientset.Interface, ipNet *net.IPNet, resyncInterval time.Duration) *IngressIPController { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartRecordingToSink(&kcoreclient.EventSinkImpl{Interface: kc.Core().Events("")}) recorder := eventBroadcaster.NewRecorder(kapi.EventSource{Component: "ingressip-controller"}) ic := &IngressIPController{ client: kc.Core(), queue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()), maxRetries: 10, recorder: recorder, } ic.cache, ic.controller = cache.NewInformer( &cache.ListWatch{ ListFunc: func(options kapi.ListOptions) (runtime.Object, error) { return ic.client.Services(kapi.NamespaceAll).List(options) }, WatchFunc: func(options kapi.ListOptions) (watch.Interface, error) { return ic.client.Services(kapi.NamespaceAll).Watch(options) }, }, &kapi.Service{}, resyncInterval, cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { service := obj.(*kapi.Service) glog.V(5).Infof("Adding service %s/%s", service.Namespace, service.Name) ic.enqueueChange(obj, nil) }, UpdateFunc: func(old, cur interface{}) { service := cur.(*kapi.Service) glog.V(5).Infof("Updating service %s/%s", service.Namespace, service.Name) ic.enqueueChange(cur, old) }, DeleteFunc: func(obj interface{}) { service := obj.(*kapi.Service) glog.V(5).Infof("Deleting service %s/%s", service.Namespace, service.Name) ic.enqueueChange(nil, obj) }, }, ) ic.changeHandler = ic.processChange ic.persistenceHandler = persistService ic.ipAllocator = ipallocator.NewAllocatorCIDRRange(ipNet, func(max int, rangeSpec string) allocator.Interface { return allocator.NewAllocationMap(max, rangeSpec) }) ic.allocationMap = make(map[string]string) ic.requeuedAllocations = sets.NewString() return ic }
func newStorage(t *testing.T) (*etcdtesting.EtcdTestServer, ipallocator.Interface, allocator.Interface, storage.Interface, factory.DestroyFunc) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") _, cidr, err := net.ParseCIDR("192.168.1.0/24") if err != nil { t.Fatal(err) } var backing allocator.Interface storage := ipallocator.NewAllocatorCIDRRange(cidr, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) backing = mem etcd := allocatoretcd.NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), etcdStorage) return etcd }) s, d := generic.NewRawStorage(etcdStorage) destroyFunc := func() { d() server.Terminate(t) } return server, storage, backing, s, destroyFunc }
// Helper that wraps NewAllocatorCIDRRange, for creating a range backed by an in-memory store. func NewCIDRRange(cidr *net.IPNet) *Range { return NewAllocatorCIDRRange(cidr, func(max int, rangeSpec string) allocator.Interface { return allocator.NewAllocationMap(max, rangeSpec) }) }
func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter genericapiserver.RESTOptionsGetter) (LegacyRESTStorage, genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *registered.GroupOrDie(api.GroupName), VersionedResourcesStorageMap: map[string]map[string]rest.Storage{}, Scheme: api.Scheme, ParameterCodec: api.ParameterCodec, NegotiatedSerializer: api.Codecs, SubresourceGroupVersionKind: map[string]unversioned.GroupVersionKind{}, } if autoscalingGroupVersion := (unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}); registered.IsEnabledVersion(autoscalingGroupVersion) { apiGroupInfo.SubresourceGroupVersionKind["replicationcontrollers/scale"] = autoscalingGroupVersion.WithKind("Scale") } var podDisruptionClient policyclient.PodDisruptionBudgetsGetter if policyGroupVersion := (unversioned.GroupVersion{Group: "policy", Version: "v1beta1"}); registered.IsEnabledVersion(policyGroupVersion) { apiGroupInfo.SubresourceGroupVersionKind["pods/eviction"] = policyGroupVersion.WithKind("Eviction") var err error podDisruptionClient, err = policyclient.NewForConfig(c.LoopbackClientConfig) if err != nil { return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err } } restStorage := LegacyRESTStorage{} podTemplateStorage := podtemplateetcd.NewREST(restOptionsGetter(api.Resource("podTemplates"))) eventStorage := eventetcd.NewREST(restOptionsGetter(api.Resource("events")), uint64(c.EventTTL.Seconds())) limitRangeStorage := limitrangeetcd.NewREST(restOptionsGetter(api.Resource("limitRanges"))) resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewREST(restOptionsGetter(api.Resource("resourceQuotas"))) secretStorage := secretetcd.NewREST(restOptionsGetter(api.Resource("secrets"))) serviceAccountStorage := serviceaccountetcd.NewREST(restOptionsGetter(api.Resource("serviceAccounts"))) persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewREST(restOptionsGetter(api.Resource("persistentVolumes"))) persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcetcd.NewREST(restOptionsGetter(api.Resource("persistentVolumeClaims"))) configMapStorage := configmapetcd.NewREST(restOptionsGetter(api.Resource("configMaps"))) namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewREST(restOptionsGetter(api.Resource("namespaces"))) restStorage.NamespaceRegistry = namespace.NewRegistry(namespaceStorage) endpointsStorage := endpointsetcd.NewREST(restOptionsGetter(api.Resource("endpoints"))) restStorage.EndpointRegistry = endpoint.NewRegistry(endpointsStorage) nodeStorage, err := nodeetcd.NewStorage(restOptionsGetter(api.Resource("nodes")), c.KubeletClientConfig, c.ProxyTransport) if err != nil { return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err } restStorage.NodeRegistry = node.NewRegistry(nodeStorage.Node) securityContextConstraintsStorage := sccetcd.NewStorage(restOptionsGetter(api.Resource("securityContextConstraints"))) podStorage := podetcd.NewStorage( restOptionsGetter(api.Resource("pods")), nodeStorage.KubeletConnectionInfo, c.ProxyTransport, podDisruptionClient, ) serviceRESTStorage, serviceStatusStorage := serviceetcd.NewREST(restOptionsGetter(api.Resource("services"))) restStorage.ServiceRegistry = service.NewRegistry(serviceRESTStorage) var serviceClusterIPRegistry rangeallocation.RangeRegistry serviceClusterIPRange := c.ServiceIPRange if serviceClusterIPRange.IP == nil { return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, fmt.Errorf("service clusterIPRange is missing") } serviceStorageConfig, err := c.StorageFactory.NewConfig(api.Resource("services")) if err != nil { return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err } ServiceClusterIPAllocator := ipallocator.NewAllocatorCIDRRange(&serviceClusterIPRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) // TODO etcdallocator package to return a storage interface via the storageFactory etcd := etcdallocator.NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), serviceStorageConfig) serviceClusterIPRegistry = etcd return etcd }) restStorage.ServiceClusterIPAllocator = serviceClusterIPRegistry var serviceNodePortRegistry rangeallocation.RangeRegistry ServiceNodePortAllocator := portallocator.NewPortAllocatorCustom(c.ServiceNodePortRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) // TODO etcdallocator package to return a storage interface via the storageFactory etcd := etcdallocator.NewEtcd(mem, "/ranges/servicenodeports", api.Resource("servicenodeportallocations"), serviceStorageConfig) serviceNodePortRegistry = etcd return etcd }) restStorage.ServiceNodePortAllocator = serviceNodePortRegistry controllerStorage := controlleretcd.NewStorage(restOptionsGetter(api.Resource("replicationControllers"))) serviceRest := service.NewStorage(restStorage.ServiceRegistry, restStorage.EndpointRegistry, ServiceClusterIPAllocator, ServiceNodePortAllocator, c.ProxyTransport) restStorageMap := map[string]rest.Storage{ "pods": podStorage.Pod, "pods/attach": podStorage.Attach, "pods/status": podStorage.Status, "pods/log": podStorage.Log, "pods/exec": podStorage.Exec, "pods/portforward": podStorage.PortForward, "pods/proxy": podStorage.Proxy, "pods/binding": podStorage.Binding, "bindings": podStorage.Binding, "podTemplates": podTemplateStorage, "replicationControllers": controllerStorage.Controller, "replicationControllers/status": controllerStorage.Status, "services": serviceRest.Service, "services/proxy": serviceRest.Proxy, "services/status": serviceStatusStorage, "endpoints": endpointsStorage, "nodes": nodeStorage.Node, "nodes/status": nodeStorage.Status, "nodes/proxy": nodeStorage.Proxy, "events": eventStorage, "limitRanges": limitRangeStorage, "resourceQuotas": resourceQuotaStorage, "resourceQuotas/status": resourceQuotaStatusStorage, "namespaces": namespaceStorage, "namespaces/status": namespaceStatusStorage, "namespaces/finalize": namespaceFinalizeStorage, "secrets": secretStorage, "serviceAccounts": serviceAccountStorage, "securityContextConstraints": securityContextConstraintsStorage, "persistentVolumes": persistentVolumeStorage, "persistentVolumes/status": persistentVolumeStatusStorage, "persistentVolumeClaims": persistentVolumeClaimStorage, "persistentVolumeClaims/status": persistentVolumeClaimStatusStorage, "configMaps": configMapStorage, "componentStatuses": componentstatus.NewStorage(componentStatusStorage{c.StorageFactory}.serversToValidate), } if registered.IsEnabledVersion(unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}) { restStorageMap["replicationControllers/scale"] = controllerStorage.Scale } if registered.IsEnabledVersion(unversioned.GroupVersion{Group: "policy", Version: "v1beta1"}) { restStorageMap["pods/eviction"] = podStorage.Eviction } apiGroupInfo.VersionedResourcesStorageMap["v1"] = restStorageMap return restStorage, apiGroupInfo, nil }
func newStorage(t *testing.T) (*Etcd, *etcdtesting.EtcdTestServer, allocator.Interface, *storagebackend.Config) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") mem := allocator.NewAllocationMap(100, "rangeSpecValue") etcd := NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), etcdStorage) return etcd, server, mem, etcdStorage }
// Helper that wraps NewAllocatorCIDRRange, for creating a range backed by an in-memory store. func NewPortAllocator(pr net.PortRange) *PortAllocator { return NewPortAllocatorCustom(pr, func(max int, rangeSpec string) allocator.Interface { return allocator.NewAllocationMap(max, rangeSpec) }) }
func (m *Master) initV1ResourcesStorage(c *Config) { restOptions := func(resource string) generic.RESTOptions { return m.restOptionsFactory.NewFor(api.Resource(resource)) } podTemplateStorage := podtemplateetcd.NewREST(restOptions("podTemplates")) eventStorage := eventetcd.NewREST(restOptions("events"), uint64(c.EventTTL.Seconds())) limitRangeStorage := limitrangeetcd.NewREST(restOptions("limitRanges")) resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewREST(restOptions("resourceQuotas")) secretStorage := secretetcd.NewREST(restOptions("secrets")) serviceAccountStorage := serviceaccountetcd.NewREST(restOptions("serviceAccounts")) persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewREST(restOptions("persistentVolumes")) persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcetcd.NewREST(restOptions("persistentVolumeClaims")) configMapStorage := configmapetcd.NewREST(restOptions("configMaps")) namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewREST(restOptions("namespaces")) m.namespaceRegistry = namespace.NewRegistry(namespaceStorage) endpointsStorage := endpointsetcd.NewREST(restOptions("endpoints")) m.endpointRegistry = endpoint.NewRegistry(endpointsStorage) nodeStorage := nodeetcd.NewStorage(restOptions("nodes"), c.KubeletClient, m.ProxyTransport) m.nodeRegistry = node.NewRegistry(nodeStorage.Node) podStorage := podetcd.NewStorage( restOptions("pods"), kubeletclient.ConnectionInfoGetter(nodeStorage.Node), m.ProxyTransport, ) serviceRESTStorage, serviceStatusStorage := serviceetcd.NewREST(restOptions("services")) m.serviceRegistry = service.NewRegistry(serviceRESTStorage) var serviceClusterIPRegistry rangeallocation.RangeRegistry serviceClusterIPRange := m.ServiceClusterIPRange if serviceClusterIPRange == nil { glog.Fatalf("service clusterIPRange is nil") return } serviceStorageConfig, err := c.StorageFactory.NewConfig(api.Resource("services")) if err != nil { glog.Fatal(err.Error()) } serviceClusterIPAllocator := ipallocator.NewAllocatorCIDRRange(serviceClusterIPRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) // TODO etcdallocator package to return a storage interface via the storageFactory etcd := etcdallocator.NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), serviceStorageConfig) serviceClusterIPRegistry = etcd return etcd }) m.serviceClusterIPAllocator = serviceClusterIPRegistry var serviceNodePortRegistry rangeallocation.RangeRegistry serviceNodePortAllocator := portallocator.NewPortAllocatorCustom(m.ServiceNodePortRange, func(max int, rangeSpec string) allocator.Interface { mem := allocator.NewAllocationMap(max, rangeSpec) // TODO etcdallocator package to return a storage interface via the storageFactory etcd := etcdallocator.NewEtcd(mem, "/ranges/servicenodeports", api.Resource("servicenodeportallocations"), serviceStorageConfig) serviceNodePortRegistry = etcd return etcd }) m.serviceNodePortAllocator = serviceNodePortRegistry controllerStorage := controlleretcd.NewStorage(restOptions("replicationControllers")) serviceRest := service.NewStorage(m.serviceRegistry, m.endpointRegistry, serviceClusterIPAllocator, serviceNodePortAllocator, m.ProxyTransport) // TODO: Factor out the core API registration m.v1ResourcesStorage = map[string]rest.Storage{ "pods": podStorage.Pod, "pods/attach": podStorage.Attach, "pods/status": podStorage.Status, "pods/log": podStorage.Log, "pods/exec": podStorage.Exec, "pods/portforward": podStorage.PortForward, "pods/proxy": podStorage.Proxy, "pods/binding": podStorage.Binding, "bindings": podStorage.Binding, "podTemplates": podTemplateStorage, "replicationControllers": controllerStorage.Controller, "replicationControllers/status": controllerStorage.Status, "services": serviceRest.Service, "services/proxy": serviceRest.Proxy, "services/status": serviceStatusStorage, "endpoints": endpointsStorage, "nodes": nodeStorage.Node, "nodes/status": nodeStorage.Status, "nodes/proxy": nodeStorage.Proxy, "events": eventStorage, "limitRanges": limitRangeStorage, "resourceQuotas": resourceQuotaStorage, "resourceQuotas/status": resourceQuotaStatusStorage, "namespaces": namespaceStorage, "namespaces/status": namespaceStatusStorage, "namespaces/finalize": namespaceFinalizeStorage, "secrets": secretStorage, "serviceAccounts": serviceAccountStorage, "persistentVolumes": persistentVolumeStorage, "persistentVolumes/status": persistentVolumeStatusStorage, "persistentVolumeClaims": persistentVolumeClaimStorage, "persistentVolumeClaims/status": persistentVolumeClaimStatusStorage, "configMaps": configMapStorage, "componentStatuses": componentstatus.NewStorage(func() map[string]apiserver.Server { return m.getServersToValidate(c) }), } if registered.IsEnabledVersion(unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}) { m.v1ResourcesStorage["replicationControllers/scale"] = controllerStorage.Scale } if registered.IsEnabledVersion(unversioned.GroupVersion{Group: "policy", Version: "v1alpha1"}) { m.v1ResourcesStorage["pods/eviction"] = podStorage.Eviction } }