mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 14:37:00 +00:00
Make master service IP static (no longer randomly assigned)
This commit is contained in:
parent
b40d079551
commit
e83fd7b8e7
@ -162,7 +162,7 @@ func startComponents(manifestURL string) (apiServerURL string) {
|
|||||||
AdmissionControl: admit.NewAlwaysAdmit(),
|
AdmissionControl: admit.NewAlwaysAdmit(),
|
||||||
ReadWritePort: portNumber,
|
ReadWritePort: portNumber,
|
||||||
ReadOnlyPort: portNumber,
|
ReadOnlyPort: portNumber,
|
||||||
PublicAddress: host,
|
PublicAddress: net.ParseIP(host),
|
||||||
})
|
})
|
||||||
handler.delegate = m.Handler
|
handler.delegate = m.Handler
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
kubeletapp "github.com/GoogleCloudPlatform/kubernetes/cmd/kubelet/app"
|
kubeletapp "github.com/GoogleCloudPlatform/kubernetes/cmd/kubelet/app"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
@ -46,7 +47,7 @@ var (
|
|||||||
masterServiceNamespace = flag.String("master_service_namespace", api.NamespaceDefault, "The namespace from which the kubernetes master services should be injected into pods")
|
masterServiceNamespace = flag.String("master_service_namespace", api.NamespaceDefault, "The namespace from which the kubernetes master services should be injected into pods")
|
||||||
)
|
)
|
||||||
|
|
||||||
func startComponents(etcdClient tools.EtcdClient, cl *client.Client, addr string, port int) {
|
func startComponents(etcdClient tools.EtcdClient, cl *client.Client, addr net.IP, port int) {
|
||||||
machineList := []string{"localhost"}
|
machineList := []string{"localhost"}
|
||||||
|
|
||||||
standalone.RunApiServer(cl, etcdClient, addr, port, *masterServiceNamespace)
|
standalone.RunApiServer(cl, etcdClient, addr, port, *masterServiceNamespace)
|
||||||
@ -57,7 +58,7 @@ func startComponents(etcdClient tools.EtcdClient, cl *client.Client, addr string
|
|||||||
standalone.SimpleRunKubelet(cl, nil, dockerClient, machineList[0], "/tmp/kubernetes", "", "127.0.0.1", 10250, *masterServiceNamespace, kubeletapp.ProbeVolumePlugins())
|
standalone.SimpleRunKubelet(cl, nil, dockerClient, machineList[0], "/tmp/kubernetes", "", "127.0.0.1", 10250, *masterServiceNamespace, kubeletapp.ProbeVolumePlugins())
|
||||||
}
|
}
|
||||||
|
|
||||||
func newApiClient(addr string, port int) *client.Client {
|
func newApiClient(addr net.IP, port int) *client.Client {
|
||||||
apiServerURL := fmt.Sprintf("http://%s:%d", addr, port)
|
apiServerURL := fmt.Sprintf("http://%s:%d", addr, port)
|
||||||
cl := client.NewOrDie(&client.Config{Host: apiServerURL, Version: testapi.Version()})
|
cl := client.NewOrDie(&client.Config{Host: apiServerURL, Version: testapi.Version()})
|
||||||
return cl
|
return cl
|
||||||
@ -73,7 +74,8 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("Failed to connect to etcd: %v", err)
|
glog.Fatalf("Failed to connect to etcd: %v", err)
|
||||||
}
|
}
|
||||||
startComponents(etcdClient, newApiClient(*addr, *port), *addr, *port)
|
address := net.ParseIP(*addr)
|
||||||
|
startComponents(etcdClient, newApiClient(address, *port), address, *port)
|
||||||
glog.Infof("Kubernetes API Server is up and running on http://%s:%d", *addr, *port)
|
glog.Infof("Kubernetes API Server is up and running on http://%s:%d", *addr, *port)
|
||||||
|
|
||||||
select {}
|
select {}
|
||||||
|
@ -97,8 +97,8 @@ type Config struct {
|
|||||||
// Defaults to 443 if not set.
|
// Defaults to 443 if not set.
|
||||||
ReadWritePort int
|
ReadWritePort int
|
||||||
|
|
||||||
// If empty, the first result from net.InterfaceAddrs will be used.
|
// If nil, the first result from net.InterfaceAddrs will be used.
|
||||||
PublicAddress string
|
PublicAddress net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// Master contains state for a Kubernetes cluster master/api server.
|
// Master contains state for a Kubernetes cluster master/api server.
|
||||||
@ -133,9 +133,14 @@ type Master struct {
|
|||||||
v1beta3 bool
|
v1beta3 bool
|
||||||
nodeIPCache IPGetter
|
nodeIPCache IPGetter
|
||||||
|
|
||||||
readOnlyServer string
|
publicIP net.IP
|
||||||
readWriteServer string
|
publicReadOnlyPort int
|
||||||
masterServices *util.Runner
|
publicReadWritePort int
|
||||||
|
serviceReadOnlyIP net.IP
|
||||||
|
serviceReadOnlyPort int
|
||||||
|
serviceReadWriteIP net.IP
|
||||||
|
serviceReadWritePort int
|
||||||
|
masterServices *util.Runner
|
||||||
|
|
||||||
// "Outputs"
|
// "Outputs"
|
||||||
Handler http.Handler
|
Handler http.Handler
|
||||||
@ -176,7 +181,7 @@ func setDefaults(c *Config) {
|
|||||||
if c.ReadWritePort == 0 {
|
if c.ReadWritePort == 0 {
|
||||||
c.ReadWritePort = 443
|
c.ReadWritePort = 443
|
||||||
}
|
}
|
||||||
for c.PublicAddress == "" {
|
for c.PublicAddress == nil {
|
||||||
// Find and use the first non-loopback address.
|
// Find and use the first non-loopback address.
|
||||||
// TODO: potentially it'd be useful to skip the docker interface if it
|
// TODO: potentially it'd be useful to skip the docker interface if it
|
||||||
// somehow is first in the list.
|
// somehow is first in the list.
|
||||||
@ -196,7 +201,7 @@ func setDefaults(c *Config) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found = true
|
found = true
|
||||||
c.PublicAddress = ip.String()
|
c.PublicAddress = ip
|
||||||
glog.Infof("Will report %v as public IP address.", ip)
|
glog.Infof("Will report %v as public IP address.", ip)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -244,6 +249,17 @@ func New(c *Config) *Master {
|
|||||||
glog.Fatalf("master.New() called with config.KubeletClient == nil")
|
glog.Fatalf("master.New() called with config.KubeletClient == nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select the first two valid IPs from portalNet to use as the master service portalIPs
|
||||||
|
serviceReadOnlyIP, err := service.GetIndexedIP(c.PortalNet, 1)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Failed to generate service read-only IP for master service: %v", err)
|
||||||
|
}
|
||||||
|
serviceReadWriteIP, err := service.GetIndexedIP(c.PortalNet, 2)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Failed to generate service read-write IP for master service: %v", err)
|
||||||
|
}
|
||||||
|
glog.Infof("Setting master service IPs based on PortalNet subnet to %q (read-only) and %q (read-write).", serviceReadOnlyIP, serviceReadWriteIP)
|
||||||
|
|
||||||
m := &Master{
|
m := &Master{
|
||||||
podRegistry: etcd.NewRegistry(c.EtcdHelper, boundPodFactory),
|
podRegistry: etcd.NewRegistry(c.EtcdHelper, boundPodFactory),
|
||||||
controllerRegistry: etcd.NewRegistry(c.EtcdHelper, nil),
|
controllerRegistry: etcd.NewRegistry(c.EtcdHelper, nil),
|
||||||
@ -268,9 +284,16 @@ func New(c *Config) *Master {
|
|||||||
v1beta3: c.EnableV1Beta3,
|
v1beta3: c.EnableV1Beta3,
|
||||||
nodeIPCache: NewIPCache(c.Cloud, util.RealClock{}, 30*time.Second),
|
nodeIPCache: NewIPCache(c.Cloud, util.RealClock{}, 30*time.Second),
|
||||||
|
|
||||||
masterCount: c.MasterCount,
|
masterCount: c.MasterCount,
|
||||||
readOnlyServer: net.JoinHostPort(c.PublicAddress, strconv.Itoa(int(c.ReadOnlyPort))),
|
publicIP: c.PublicAddress,
|
||||||
readWriteServer: net.JoinHostPort(c.PublicAddress, strconv.Itoa(int(c.ReadWritePort))),
|
publicReadOnlyPort: c.ReadOnlyPort,
|
||||||
|
publicReadWritePort: c.ReadWritePort,
|
||||||
|
serviceReadOnlyIP: serviceReadOnlyIP,
|
||||||
|
// TODO: serviceReadOnlyPort should be passed in as an argument, it may not always be 80
|
||||||
|
serviceReadOnlyPort: 80,
|
||||||
|
serviceReadWriteIP: serviceReadWriteIP,
|
||||||
|
// TODO: serviceReadWritePort should be passed in as an argument, it may not always be 443
|
||||||
|
serviceReadWritePort: 443,
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.RestfulContainer != nil {
|
if c.RestfulContainer != nil {
|
||||||
@ -443,7 +466,7 @@ func (m *Master) init(c *Config) {
|
|||||||
func (m *Master) InstallSwaggerAPI() {
|
func (m *Master) InstallSwaggerAPI() {
|
||||||
// Enable swagger UI and discovery API
|
// Enable swagger UI and discovery API
|
||||||
swaggerConfig := swagger.Config{
|
swaggerConfig := swagger.Config{
|
||||||
WebServicesUrl: m.readWriteServer,
|
WebServicesUrl: net.JoinHostPort(m.publicIP.String(), strconv.Itoa(int(m.publicReadWritePort))),
|
||||||
WebServices: m.handlerContainer.RegisteredWebServices(),
|
WebServices: m.handlerContainer.RegisteredWebServices(),
|
||||||
// TODO: Parameterize the path?
|
// TODO: Parameterize the path?
|
||||||
ApiPath: "/swaggerapi/",
|
ApiPath: "/swaggerapi/",
|
||||||
|
@ -18,6 +18,8 @@ package master
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
@ -32,12 +34,11 @@ func (m *Master) serviceWriterLoop(stop chan struct{}) {
|
|||||||
// TODO: when it becomes possible to change this stuff,
|
// TODO: when it becomes possible to change this stuff,
|
||||||
// stop polling and start watching.
|
// stop polling and start watching.
|
||||||
// TODO: add endpoints of all replicas, not just the elected master.
|
// TODO: add endpoints of all replicas, not just the elected master.
|
||||||
if m.readWriteServer != "" {
|
if m.serviceReadWriteIP != nil {
|
||||||
// TODO: the public port should be part of the argument here, port will not always be 443
|
if err := m.createMasterServiceIfNeeded("kubernetes", m.serviceReadWriteIP, m.serviceReadWritePort); err != nil {
|
||||||
if err := m.createMasterServiceIfNeeded("kubernetes", 443); err != nil {
|
|
||||||
glog.Errorf("Can't create rw service: %v", err)
|
glog.Errorf("Can't create rw service: %v", err)
|
||||||
}
|
}
|
||||||
if err := m.ensureEndpointsContain("kubernetes", m.readWriteServer); err != nil {
|
if err := m.ensureEndpointsContain("kubernetes", net.JoinHostPort(m.publicIP.String(), strconv.Itoa(int(m.publicReadWritePort)))); err != nil {
|
||||||
glog.Errorf("Can't create rw endpoints: %v", err)
|
glog.Errorf("Can't create rw endpoints: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,12 +56,11 @@ func (m *Master) roServiceWriterLoop(stop chan struct{}) {
|
|||||||
// Update service & endpoint records.
|
// Update service & endpoint records.
|
||||||
// TODO: when it becomes possible to change this stuff,
|
// TODO: when it becomes possible to change this stuff,
|
||||||
// stop polling and start watching.
|
// stop polling and start watching.
|
||||||
if m.readOnlyServer != "" {
|
if m.serviceReadOnlyIP != nil {
|
||||||
// TODO: the public port should be part of the argument here, port will not always be 80
|
if err := m.createMasterServiceIfNeeded("kubernetes-ro", m.serviceReadOnlyIP, m.serviceReadOnlyPort); err != nil {
|
||||||
if err := m.createMasterServiceIfNeeded("kubernetes-ro", 80); err != nil {
|
|
||||||
glog.Errorf("Can't create ro service: %v", err)
|
glog.Errorf("Can't create ro service: %v", err)
|
||||||
}
|
}
|
||||||
if err := m.ensureEndpointsContain("kubernetes-ro", m.readOnlyServer); err != nil {
|
if err := m.ensureEndpointsContain("kubernetes-ro", net.JoinHostPort(m.publicIP.String(), strconv.Itoa(int(m.publicReadOnlyPort)))); err != nil {
|
||||||
glog.Errorf("Can't create ro endpoints: %v", err)
|
glog.Errorf("Can't create ro endpoints: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ func (m *Master) roServiceWriterLoop(stop chan struct{}) {
|
|||||||
|
|
||||||
// createMasterServiceIfNeeded will create the specified service if it
|
// createMasterServiceIfNeeded will create the specified service if it
|
||||||
// doesn't already exist.
|
// doesn't already exist.
|
||||||
func (m *Master) createMasterServiceIfNeeded(serviceName string, port int) error {
|
func (m *Master) createMasterServiceIfNeeded(serviceName string, serviceIP net.IP, servicePort int) error {
|
||||||
ctx := api.NewDefaultContext()
|
ctx := api.NewDefaultContext()
|
||||||
if _, err := m.serviceRegistry.GetService(ctx, serviceName); err == nil {
|
if _, err := m.serviceRegistry.GetService(ctx, serviceName); err == nil {
|
||||||
// The service already exists.
|
// The service already exists.
|
||||||
@ -88,9 +88,10 @@ func (m *Master) createMasterServiceIfNeeded(serviceName string, port int) error
|
|||||||
Labels: map[string]string{"provider": "kubernetes", "component": "apiserver"},
|
Labels: map[string]string{"provider": "kubernetes", "component": "apiserver"},
|
||||||
},
|
},
|
||||||
Spec: api.ServiceSpec{
|
Spec: api.ServiceSpec{
|
||||||
Port: port,
|
Port: servicePort,
|
||||||
// maintained by this code, not by the pod selector
|
// maintained by this code, not by the pod selector
|
||||||
Selector: nil,
|
Selector: nil,
|
||||||
|
PortalIP: serviceIP.String(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Kids, don't do this at home: this is a hack. There's no good way to call the business
|
// Kids, don't do this at home: this is a hack. There's no good way to call the business
|
||||||
|
@ -47,7 +47,7 @@ import (
|
|||||||
type APIServer struct {
|
type APIServer struct {
|
||||||
Port int
|
Port int
|
||||||
Address util.IP
|
Address util.IP
|
||||||
PublicAddressOverride string
|
PublicAddressOverride util.IP
|
||||||
ReadOnlyPort int
|
ReadOnlyPort int
|
||||||
APIRate float32
|
APIRate float32
|
||||||
APIBurst int
|
APIBurst int
|
||||||
@ -80,6 +80,7 @@ func NewAPIServer() *APIServer {
|
|||||||
s := APIServer{
|
s := APIServer{
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
Address: util.IP(net.ParseIP("127.0.0.1")),
|
Address: util.IP(net.ParseIP("127.0.0.1")),
|
||||||
|
PublicAddressOverride: util.IP(net.ParseIP("")),
|
||||||
ReadOnlyPort: 7080,
|
ReadOnlyPort: 7080,
|
||||||
APIRate: 10.0,
|
APIRate: 10.0,
|
||||||
APIBurst: 200,
|
APIBurst: 200,
|
||||||
@ -127,11 +128,10 @@ func (s *APIServer) AddFlags(fs *pflag.FlagSet) {
|
|||||||
"further assumed that port 443 on the cluster's public address is proxied to this "+
|
"further assumed that port 443 on the cluster's public address is proxied to this "+
|
||||||
"port. This is performed by nginx in the default setup.")
|
"port. This is performed by nginx in the default setup.")
|
||||||
fs.Var(&s.Address, "address", "The IP address on to serve on (set to 0.0.0.0 for all interfaces)")
|
fs.Var(&s.Address, "address", "The IP address on to serve on (set to 0.0.0.0 for all interfaces)")
|
||||||
fs.StringVar(&s.PublicAddressOverride, "public_address_override", s.PublicAddressOverride, ""+
|
fs.Var(&s.PublicAddressOverride, "public_address_override", "Public serving address."+
|
||||||
"Public serving address. Read only port will be opened on this address, "+
|
"Read only port will be opened on this address, and it is assumed that port "+
|
||||||
"and it is assumed that port 443 at this address will be proxied/redirected "+
|
"443 at this address will be proxied/redirected to '-address':'-port'. If "+
|
||||||
"to '-address':'-port'. If blank, the address in the first listed interface "+
|
"blank, the address in the first listed interface will be used.")
|
||||||
"will be used.")
|
|
||||||
fs.IntVar(&s.ReadOnlyPort, "read_only_port", s.ReadOnlyPort, ""+
|
fs.IntVar(&s.ReadOnlyPort, "read_only_port", s.ReadOnlyPort, ""+
|
||||||
"The port from which to serve read-only resources. If 0, don't serve on a "+
|
"The port from which to serve read-only resources. If 0, don't serve on a "+
|
||||||
"read-only address. It is assumed that firewall rules are set up such that "+
|
"read-only address. It is assumed that firewall rules are set up such that "+
|
||||||
@ -251,7 +251,7 @@ func (s *APIServer) Run(_ []string) error {
|
|||||||
CorsAllowedOriginList: s.CorsAllowedOriginList,
|
CorsAllowedOriginList: s.CorsAllowedOriginList,
|
||||||
ReadOnlyPort: s.ReadOnlyPort,
|
ReadOnlyPort: s.ReadOnlyPort,
|
||||||
ReadWritePort: s.Port,
|
ReadWritePort: s.Port,
|
||||||
PublicAddress: s.PublicAddressOverride,
|
PublicAddress: net.IP(s.PublicAddressOverride),
|
||||||
Authenticator: authenticator,
|
Authenticator: authenticator,
|
||||||
Authorizer: authorizer,
|
Authorizer: authorizer,
|
||||||
AdmissionControl: admissionController,
|
AdmissionControl: admissionController,
|
||||||
@ -263,11 +263,11 @@ func (s *APIServer) Run(_ []string) error {
|
|||||||
// We serve on 3 ports. See docs/reaching_the_api.md
|
// We serve on 3 ports. See docs/reaching_the_api.md
|
||||||
roLocation := ""
|
roLocation := ""
|
||||||
if s.ReadOnlyPort != 0 {
|
if s.ReadOnlyPort != 0 {
|
||||||
roLocation = net.JoinHostPort(config.PublicAddress, strconv.Itoa(config.ReadOnlyPort))
|
roLocation = net.JoinHostPort(config.PublicAddress.String(), strconv.Itoa(config.ReadOnlyPort))
|
||||||
}
|
}
|
||||||
secureLocation := ""
|
secureLocation := ""
|
||||||
if s.SecurePort != 0 {
|
if s.SecurePort != 0 {
|
||||||
secureLocation = net.JoinHostPort(config.PublicAddress, strconv.Itoa(s.SecurePort))
|
secureLocation = net.JoinHostPort(config.PublicAddress.String(), strconv.Itoa(s.SecurePort))
|
||||||
}
|
}
|
||||||
rwLocation := net.JoinHostPort(s.Address.String(), strconv.Itoa(int(s.Port)))
|
rwLocation := net.JoinHostPort(s.Address.String(), strconv.Itoa(int(s.Port)))
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ func (s *APIServer) Run(_ []string) error {
|
|||||||
if s.TLSCertFile == "" && s.TLSPrivateKeyFile == "" {
|
if s.TLSCertFile == "" && s.TLSPrivateKeyFile == "" {
|
||||||
s.TLSCertFile = "/var/run/kubernetes/apiserver.crt"
|
s.TLSCertFile = "/var/run/kubernetes/apiserver.crt"
|
||||||
s.TLSPrivateKeyFile = "/var/run/kubernetes/apiserver.key"
|
s.TLSPrivateKeyFile = "/var/run/kubernetes/apiserver.key"
|
||||||
if err := util.GenerateSelfSignedCert(config.PublicAddress, s.TLSCertFile, s.TLSPrivateKeyFile); err != nil {
|
if err := util.GenerateSelfSignedCert(config.PublicAddress.String(), s.TLSCertFile, s.TLSPrivateKeyFile); err != nil {
|
||||||
glog.Errorf("Unable to generate self signed cert: %v", err)
|
glog.Errorf("Unable to generate self signed cert: %v", err)
|
||||||
} else {
|
} else {
|
||||||
glog.Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile)
|
glog.Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile)
|
||||||
|
@ -174,6 +174,18 @@ func (ipa *ipAllocator) AllocateNext() (net.IP, error) {
|
|||||||
return nil, fmt.Errorf("can't find a free IP in %s", ipa.subnet)
|
return nil, fmt.Errorf("can't find a free IP in %s", ipa.subnet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the index-th IP from the specified subnet range.
|
||||||
|
// For example, subnet "10.0.0.0/24" with index "2" will return the IP "10.0.0.2".
|
||||||
|
// TODO(saad-ali): Move this (and any other functions that are independent of ipAllocator) to some
|
||||||
|
// place more generic.
|
||||||
|
func GetIndexedIP(subnet *net.IPNet, index int) (net.IP, error) {
|
||||||
|
ip := ipAdd(subnet.IP, index /* offset */)
|
||||||
|
if !subnet.Contains(ip) {
|
||||||
|
return nil, fmt.Errorf("can't generate IP with index %d from subnet. subnet too small. subnet: %q", index, subnet)
|
||||||
|
}
|
||||||
|
return ip, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ipa *ipAllocator) createRandomIp() net.IP {
|
func (ipa *ipAllocator) createRandomIp() net.IP {
|
||||||
ip := ipa.subnet.IP
|
ip := ipa.subnet.IP
|
||||||
mask := ipa.subnet.Mask
|
mask := ipa.subnet.Mask
|
||||||
|
@ -214,6 +214,75 @@ func TestIPAdd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGenerateFirstTwoIPsFromSubnet(t *testing.T) {
|
||||||
|
// Arrange
|
||||||
|
testCases := []struct {
|
||||||
|
subnet string
|
||||||
|
expected1stIP string
|
||||||
|
expected2ndIP string
|
||||||
|
}{
|
||||||
|
{"10.0.0.0/24", "10.0.0.1", "10.0.0.2"},
|
||||||
|
{"10.10.10.10/24", "10.10.10.1", "10.10.10.2"},
|
||||||
|
{"10.10.10.10/16", "10.10.0.1", "10.10.0.2"},
|
||||||
|
{"10.10.10.10/8", "10.0.0.1", "10.0.0.2"},
|
||||||
|
{"10.10.10.10/0", "0.0.0.1", "0.0.0.2"},
|
||||||
|
{"192.168.100.1/16", "192.168.0.1", "192.168.0.2"},
|
||||||
|
{"153.15.250.5/23", "153.15.250.1", "153.15.250.2"},
|
||||||
|
{"2001:db8::/48", "2001:db8::1", "2001:db8::2"},
|
||||||
|
{"2001:db8:123:255::/48", "2001:db8:123::1", "2001:db8:123::2"},
|
||||||
|
{"12.12.0.0/30", "12.12.0.1", "12.12.0.2"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
_, subnet, _ := net.ParseCIDR(testCase.subnet)
|
||||||
|
firstIP, err := GetIndexedIP(subnet, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
secondIP, err := GetIndexedIP(subnet, 2)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if firstIP.String() != testCase.expected1stIP {
|
||||||
|
t.Errorf("Unexpected first IP: Expected <%q> Actual <%q>", testCase.expected1stIP, firstIP.String())
|
||||||
|
}
|
||||||
|
if secondIP.String() != testCase.expected2ndIP {
|
||||||
|
t.Errorf("Unexpected second IP: Expected <%q> Actual <%q>", testCase.expected2ndIP, secondIP.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetIndexedIPSubnetTooSmall(t *testing.T) {
|
||||||
|
// Arrange
|
||||||
|
testCases := []struct {
|
||||||
|
subnet string
|
||||||
|
}{
|
||||||
|
{"12.12.0.0/32"},
|
||||||
|
{"12.12.0.0/31"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
_, subnet, _ := net.ParseCIDR(testCase.subnet)
|
||||||
|
secondIP, err := GetIndexedIP(subnet, 2)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected error but no error occured for subnet: ", testCase.subnet)
|
||||||
|
}
|
||||||
|
thirdIP, err := GetIndexedIP(subnet, 3)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected error but no error occured for subnet: ", testCase.subnet)
|
||||||
|
}
|
||||||
|
if secondIP != nil {
|
||||||
|
t.Errorf("Unexpected second IP: Expected nil Actual <%q>", thirdIP.String())
|
||||||
|
}
|
||||||
|
if thirdIP != nil {
|
||||||
|
t.Errorf("Unexpected third IP: Expected nil Actual <%q>", secondIP.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCopyIP(t *testing.T) {
|
func TestCopyIP(t *testing.T) {
|
||||||
ip1 := net.ParseIP("1.2.3.4")
|
ip1 := net.ParseIP("1.2.3.4")
|
||||||
ip2 := copyIP(ip1)
|
ip2 := copyIP(ip1)
|
||||||
|
@ -85,7 +85,7 @@ func GetAPIServerClient(authPath string, apiServerList util.StringList) (*client
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RunApiServer starts an API server in a go routine.
|
// RunApiServer starts an API server in a go routine.
|
||||||
func RunApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr string, port int, masterServiceNamespace string) {
|
func RunApiServer(cl *client.Client, etcdClient tools.EtcdClient, addr net.IP, port int, masterServiceNamespace string) {
|
||||||
handler := delegateHandler{}
|
handler := delegateHandler{}
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(etcdClient, "")
|
helper, err := master.NewEtcdHelper(etcdClient, "")
|
||||||
|
@ -106,7 +106,7 @@ var aService string = `
|
|||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta1",
|
||||||
"id": "a",
|
"id": "a",
|
||||||
"port": 8000,
|
"port": 8000,
|
||||||
"portalIP": "10.0.0.1",
|
"portalIP": "10.0.0.100",
|
||||||
"labels": { "name": "a" },
|
"labels": { "name": "a" },
|
||||||
"selector": { "name": "a" }
|
"selector": { "name": "a" }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user