1
16
17 package util
18
19 import (
20 "net"
21 "net/url"
22 "strconv"
23
24 "github.com/pkg/errors"
25
26 "k8s.io/apimachinery/pkg/util/validation"
27 "k8s.io/klog/v2"
28 netutils "k8s.io/utils/net"
29
30 kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
31 )
32
33
34
35
36
37 func GetControlPlaneEndpoint(controlPlaneEndpoint string, localEndpoint *kubeadmapi.APIEndpoint) (string, error) {
38
39 localAPIEndpoint, err := GetLocalAPIEndpoint(localEndpoint)
40 if err != nil {
41 return "", err
42 }
43
44
45 if len(controlPlaneEndpoint) > 0 {
46
47 var host, port string
48 var err error
49 if host, port, err = ParseHostPort(controlPlaneEndpoint); err != nil {
50 return "", errors.Wrapf(err, "invalid value %q given for controlPlaneEndpoint", controlPlaneEndpoint)
51 }
52
53
54 localEndpointPort := strconv.Itoa(int(localEndpoint.BindPort))
55 if port != "" {
56 if port != localEndpointPort {
57 klog.Warning("[endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address")
58 }
59 } else {
60 port = localEndpointPort
61 }
62
63
64 return formatURL(host, port).String(), nil
65 }
66
67 return localAPIEndpoint, nil
68 }
69
70
71
72 func GetLocalAPIEndpoint(localEndpoint *kubeadmapi.APIEndpoint) (string, error) {
73
74 localEndpointIP, localEndpointPort, err := parseAPIEndpoint(localEndpoint)
75 if err != nil {
76 return "", err
77 }
78 url := formatURL(localEndpointIP.String(), localEndpointPort)
79 return url.String(), nil
80 }
81
82
83
84
85 func ParseHostPort(hostport string) (string, string, error) {
86 var host, port string
87 var err error
88
89
90 if host, port, err = net.SplitHostPort(hostport); err != nil {
91
92 host = hostport
93 }
94
95
96 if port != "" {
97 if _, err := ParsePort(port); err != nil {
98 return "", "", errors.Errorf("hostport %s: port %s must be a valid number between 1 and 65535, inclusive", hostport, port)
99 }
100 }
101
102
103 if ip := netutils.ParseIPSloppy(host); ip != nil {
104 return host, port, nil
105 }
106
107
108 if errs := validation.IsDNS1123Subdomain(host); len(errs) == 0 {
109 return host, port, nil
110 }
111
112 return "", "", errors.Errorf("hostport %s: host '%s' must be a valid IP address or a valid RFC-1123 DNS subdomain", hostport, host)
113 }
114
115
116
117 func ParsePort(port string) (int, error) {
118 portInt, err := netutils.ParsePort(port, true)
119 if err == nil && (1 <= portInt && portInt <= 65535) {
120 return portInt, nil
121 }
122
123 return 0, errors.New("port must be a valid number between 1 and 65535, inclusive")
124 }
125
126
127
128 func parseAPIEndpoint(localEndpoint *kubeadmapi.APIEndpoint) (net.IP, string, error) {
129
130 bindPortString := strconv.Itoa(int(localEndpoint.BindPort))
131 if _, err := ParsePort(bindPortString); err != nil {
132 return nil, "", errors.Wrapf(err, "invalid value %q given for api.bindPort", localEndpoint.BindPort)
133 }
134
135
136 var ip = netutils.ParseIPSloppy(localEndpoint.AdvertiseAddress)
137 if ip == nil {
138 return nil, "", errors.Errorf("invalid value `%s` given for api.advertiseAddress", localEndpoint.AdvertiseAddress)
139 }
140
141 return ip, bindPortString, nil
142 }
143
144
145 func formatURL(host, port string) *url.URL {
146 return &url.URL{
147 Scheme: "https",
148 Host: net.JoinHostPort(host, port),
149 }
150 }
151
View as plain text