// Copyright (c) 2017 VMware, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "fmt" "math/rand" "net" "net/url" "strings" "time" "github.com/vmware/harbor/src/common/utils/log" ) // FormatEndpoint formats endpoint func FormatEndpoint(endpoint string) string { endpoint = strings.TrimSpace(endpoint) endpoint = strings.TrimRight(endpoint, "/") if !strings.HasPrefix(endpoint, "http://") && !strings.HasPrefix(endpoint, "https://") { endpoint = "http://" + endpoint } return endpoint } // ParseEndpoint parses endpoint to a URL func ParseEndpoint(endpoint string) (*url.URL, error) { endpoint = FormatEndpoint(endpoint) u, err := url.Parse(endpoint) if err != nil { return nil, err } return u, nil } // ParseRepository splits a repository into two parts: project and rest func ParseRepository(repository string) (project, rest string) { repository = strings.TrimLeft(repository, "/") repository = strings.TrimRight(repository, "/") if !strings.ContainsRune(repository, '/') { rest = repository return } index := strings.Index(repository, "/") project = repository[0:index] rest = repository[index+1:] return } // GenerateRandomString generates a random string func GenerateRandomString() string { length := 32 rand.Seed(time.Now().UTC().UnixNano()) const chars = "abcdefghijklmnopqrstuvwxyz0123456789" result := make([]byte, length) for i := 0; i < length; i++ { result[i] = chars[rand.Intn(len(chars))] } return string(result) } // TestTCPConn tests TCP connection // timeout: the total time before returning if something is wrong // with the connection, in second // interval: the interval time for retring after failure, in second func TestTCPConn(addr string, timeout, interval int) error { success := make(chan int) cancel := make(chan int) go func() { for { select { case <-cancel: break default: conn, err := net.DialTimeout("tcp", addr, time.Duration(timeout)*time.Second) if err != nil { log.Errorf("failed to connect to tcp://%s, retry after %d seconds :%v", addr, interval, err) time.Sleep(time.Duration(interval) * time.Second) continue } conn.Close() success <- 1 break } } }() select { case <-success: return nil case <-time.After(time.Duration(timeout) * time.Second): cancel <- 1 return fmt.Errorf("failed to connect to tcp:%s after %d seconds", addr, timeout) } }