Change:
On GCE, if you create a cluster with a name like , then KCM will fail to create the routes, because it includes the cluster name in the route name, but does not escape it to meet GCE requirements. See The following error is logged (lightly edited): Possible solutions: In kops I have built an escaping that is URL inspired, but instead of %2F I use -2F We could just replace every invalid character with a dash or simply omit it. We truncate this anyway, so we do expect collisions at this level (the nameHint is the node UUID and gives us uniqueness)
/sig cluster-lifecycle /area platform/gce since we lack a sig-gcp at the moment
This relates to
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. Prevent issues from auto-closing with an comment. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
Stale issues rot after 30d of inactivity. Mark the issue as fresh with . Rotten issues close after an additional 30d of inactivity. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle rotten /remove-lifecycle stale
Rotten issues close after 30d of inactivity. Reopen the issue with . Mark the issue as fresh with . Send feedback to sig-testing, kubernetes/test-infra and/or . /close

Discussion:
// AddService starts listening for a new service on a given port. func (proxier Proxier) AddService(service string, port int) error { // Make sure we can start listening on the port before saying all's well. <del> ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) </del> <ins> l, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) </ins> if err != nil { return err } <del> log.Printf("Listening for %s on %d", service, port) // If that succeeds, start the accepting loop. go proxier.AcceptHandler(service, ln) </del> <ins> proxier.addServiceCommon(service, l) </ins> return nil } <ins> // addService starts listening for a new service, returning the port it's using. // For testing on a system with unknown ports used. func (proxier Proxier) addServiceOnUnusedPort(service string) (string, error) { // Make sure we can start listening on the port before saying all's well. l, err := net.Listen("tcp", ":") if err != nil { return "", err } proxier.addServiceCommon(service, l) _, port, err := net.SplitHostPort(l.Addr().String()) return port, nil } func (proxier Proxier) addServiceCommon(service string, l net.Listener) { log.Printf("Listening for %s on %s", service, l.Addr().String()) // If that succeeds, start the accepting loop. go proxier.AcceptHandler(service, l) } </ins> func (proxier Proxier) OnUpdate(services []api.Service) { log.Printf("Received update notice: %+v", services) for _, service := range services {

"github.com/GoogleCloudPlatform/kubernetes/pkg/api" ) <del> // a simple echoServer that only accept one connection func echoServer(addr string) error { </del> <ins> // a simple echoServer that only accepts one connection. Returns port actually // being listened on, or an error. func echoServer(t *testing.T, addr string) (string, error) { </ins> l, err := net.Listen("tcp", addr) if err != nil { <del> return fmt.Errorf("failed to start echo service: %v", err) </del> <ins> return "", fmt.Errorf("failed to start echo service: %v", err) </ins> } <del> defer l.Close() conn, err := l.Accept() if err != nil { return fmt.Errorf("failed to accept new conn to echo service: %v", err) } io.Copy(conn, conn) conn.Close() return nil } func TestProxy(t *testing.T) { </del> go func() { <del> if err := echoServer("127.0.0.1:2222"); err != nil { t.Fatal(err) </del> <ins> defer l.Close() conn, err := l.Accept() if err != nil { t.Errorf("failed to accept new conn to echo service: %v", err) </ins> } <ins> io.Copy(conn, conn) conn.Close() </ins> }() <ins> _, port, err := net.SplitHostPort(l.Addr().String()) return port, err } func TestProxy(t *testing.T) { port, err := echoServer(t, "127.0.0.1:") if err != nil { t.Fatal(err) } </ins> lb := NewLoadBalancerRR() <del> lb.OnUpdate([]api.Endpoints{{"echo", []string{"127.0.0.1:2222"}}}) </del> <ins> lb.OnUpdate([]api.Endpoints{{"echo", []string{net.JoinHostPort("127.0.0.1", port)}}}) </ins> p := NewProxier(lb) <del> if err := p.AddService("echo", 2223); err != nil { t.Fatalf("error adding new service: %v", err) </del> <ins> proxyPort, err := p.addServiceOnUnusedPort("echo") if err != nil { t.Fatalf("error adding new service: %#v", err) </ins> } <del> conn, err := net.Dial("tcp", "127.0.0.1:2223") </del> <ins> conn, err := net.Dial("tcp", net.JoinHostPort("127.0.0.1", proxyPort)) </ins> if err != nil { t.Fatalf("error connecting to proxy: %v", err) }