diff --git a/host-to-ip.go b/host-to-ip.go new file mode 100644 index 000000000..7cda67c9e --- /dev/null +++ b/host-to-ip.go @@ -0,0 +1,47 @@ +/* + * Minio Cloud Storage, (C) 2016 Minio, Inc. + * + * 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 main + +import ( + "net" + "sort" +) + +// byLastOctet implements sort.Interface used in sorting a list +// of ip address by their last octet value. +type byLastOctet []net.IP + +func (n byLastOctet) Len() int { return len(n) } +func (n byLastOctet) Swap(i, j int) { n[i], n[j] = n[j], n[i] } +func (n byLastOctet) Less(i, j int) bool { + return []byte(n[i].To4())[3] < []byte(n[j].To4())[3] +} + +// getIPsFromHosts - returns a reverse sorted list of ips based on the last octet value. +func getIPsFromHosts(hosts []string) (ips []net.IP) { + for _, host := range hosts { + ips = append(ips, net.ParseIP(host)) + } + // Reverse sort ips by their last octet. + sort.Sort(sort.Reverse(byLastOctet(ips))) + return ips +} + +// getHostToIP - parses a host string into net.IP value. +func getHostToIP(host string) net.IP { + return net.ParseIP(host) +} diff --git a/host-to-ip_test.go b/host-to-ip_test.go new file mode 100644 index 000000000..1fa041e68 --- /dev/null +++ b/host-to-ip_test.go @@ -0,0 +1,61 @@ +/* + * Minio Cloud Storage, (C) 2016 Minio, Inc. + * + * 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 main + +import "testing" + +// Tests sorted list generated from hosts to ip. +func TestHostToIP(t *testing.T) { + // Collection of test cases to validate last octet sorting. + testCases := []struct { + hosts []string + sortedHosts []string + }{ + { + // List of ip addresses that need to be sorted. + []string{ + "129.95.30.40", + "5.24.69.2", + "19.20.203.5", + "1.2.3.4", + "127.0.0.1", + "19.20.21.22", + "5.220.100.50", + }, + // Numerical sorting result based on the last octet. + []string{ + "5.220.100.50", + "129.95.30.40", + "19.20.21.22", + "19.20.203.5", + "1.2.3.4", + "5.24.69.2", + "127.0.0.1", + }, + }, + } + + // Tests the correct sorting behavior of getIPsFromHosts. + for j, testCase := range testCases { + ips := getIPsFromHosts(testCase.hosts) + for i, ip := range ips { + if ip.String() != testCase.sortedHosts[i] { + t.Fatalf("Test %d expected to pass but failed. Wanted ip %s, but got %s", j+1, testCase.sortedHosts[i], ip.String()) + } + } + } +} diff --git a/server-main.go b/server-main.go index ceb17c8f5..eb0c62a19 100644 --- a/server-main.go +++ b/server-main.go @@ -21,7 +21,6 @@ import ( "net" "net/http" "os" - "sort" "strconv" "strings" "time" @@ -140,13 +139,14 @@ func finalizeEndpoints(tls bool, apiServer *http.Server) (endPoints []string) { scheme = "https" } + ips := getIPsFromHosts(hosts) + // Construct proper endpoints. - for _, host := range hosts { - endPoints = append(endPoints, fmt.Sprintf("%s://%s:%s", scheme, host, port)) + for _, ip := range ips { + endPoints = append(endPoints, fmt.Sprintf("%s://%s:%s", scheme, ip.String(), port)) } // Success. - sort.Strings(endPoints) return endPoints }