...
1 package info
2
3 import (
4 "context"
5 "errors"
6 "net"
7
8 corev1 "k8s.io/api/core/v1"
9 kerrors "k8s.io/apimachinery/pkg/api/errors"
10 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11 "k8s.io/apimachinery/pkg/types"
12
13 "sigs.k8s.io/controller-runtime/pkg/client"
14
15 calico "edge-infra.dev/pkg/k8s/net/calico"
16 "edge-infra.dev/pkg/sds/ien"
17 )
18
19 const (
20 clusterDNSKey = "cluster-dns-ip"
21 podSubnetKey = "pod-network-cidr"
22 serviceSubnetKey = "service-network-cidr"
23 egressTunnelSubnetKey = "egress-tunnels-cidr"
24
25 PodSubnetDefault string = "100.127.0.0/16"
26
27 ClusterDNSDefault string = "10.96.0.10"
28
29 ServiceSubnetDefault string = "10.96.0.0/16"
30
31 EgressTunnelSubnetDefault string = "10.80.0.0/22"
32 )
33
34 const (
35 Namespace string = "sds"
36 Name string = "network-service-ips"
37 )
38
39 var (
40 ErrInvalidClusterDNSIP = errors.New("invalid cluster dns ip address")
41 ErrInvalidPodSubnet = errors.New("invalid pod subnet")
42 ErrInvalidServiceSubnet = errors.New("invalid service subnet")
43 ErrInvalidEgressTunnelSubnet = errors.New("invalid egress gateway tunnel subnet")
44 )
45
46 type Info struct {
47 PodSubnet string
48 ClusterDNSIP string
49 ServiceSubnet string
50 EgressTunnelSubnet string
51 }
52
53
54 func New() *Info {
55 return &Info{
56 PodSubnet: PodSubnetDefault,
57 ServiceSubnet: ServiceSubnetDefault,
58 ClusterDNSIP: ClusterDNSDefault,
59 EgressTunnelSubnet: EgressTunnelSubnetDefault,
60 }
61 }
62
63
64 func (i *Info) FromClient(ctx context.Context, k8sClient client.Client) (*Info, error) {
65 cm := &corev1.ConfigMap{}
66 if err := k8sClient.Get(ctx, configMapKey(), cm); kerrors.IsNotFound(err) {
67 return New(), nil
68 } else if err != nil {
69 return nil, err
70 }
71 return i.FromConfigMap(cm), nil
72 }
73
74
75 func (i *Info) FromConfigMap(cm *corev1.ConfigMap) *Info {
76 i = New()
77 if cm.Data[clusterDNSKey] != "" {
78 i.ClusterDNSIP = cm.Data[clusterDNSKey]
79 }
80 if cm.Data[podSubnetKey] != "" {
81 i.PodSubnet = cm.Data[podSubnetKey]
82 }
83 if cm.Data[serviceSubnetKey] != "" {
84 i.ServiceSubnet = cm.Data[serviceSubnetKey]
85 }
86 if cm.Data[egressTunnelSubnetKey] != "" {
87 i.EgressTunnelSubnet = cm.Data[egressTunnelSubnetKey]
88 }
89 return i
90 }
91
92 func (i *Info) ToConfigMap() *corev1.ConfigMap {
93 return &corev1.ConfigMap{
94 TypeMeta: typemeta(),
95 ObjectMeta: metadata(),
96 Data: map[string]string{
97 clusterDNSKey: i.ClusterDNSIP,
98 podSubnetKey: i.PodSubnet,
99 serviceSubnetKey: i.ServiceSubnet,
100 egressTunnelSubnetKey: i.EgressTunnelSubnet,
101 },
102 }
103 }
104
105
106 func (i *Info) Validate() error {
107 if ip := net.ParseIP(i.ClusterDNSIP); ip == nil {
108 return ErrInvalidClusterDNSIP
109 }
110 if _, _, err := net.ParseCIDR(i.EgressTunnelSubnet); err != nil {
111 return ErrInvalidEgressTunnelSubnet
112 }
113 if _, _, err := net.ParseCIDR(i.PodSubnet); err != nil {
114 return ErrInvalidPodSubnet
115 }
116 if _, _, err := net.ParseCIDR(i.ServiceSubnet); err != nil {
117 return ErrInvalidServiceSubnet
118 }
119 return nil
120 }
121
122 func configMapKey() client.ObjectKey {
123 return client.ObjectKey{Namespace: Namespace, Name: Name}
124 }
125
126
127 func newNetworkInfoConfigMap() corev1.ConfigMap {
128 return corev1.ConfigMap{
129 TypeMeta: typemeta(),
130 ObjectMeta: metadata(),
131 }
132 }
133
134
135 func typemeta() metav1.TypeMeta {
136 return metav1.TypeMeta{
137 Kind: "ConfigMap",
138 APIVersion: corev1.SchemeGroupVersion.String(),
139 }
140 }
141
142
143 func metadata() metav1.ObjectMeta {
144 return metav1.ObjectMeta{
145 Name: configMapKey().Name,
146 Namespace: configMapKey().Namespace,
147 }
148 }
149
150 var (
151 ErrNodeCIDRNotFound = errors.New("could not find a unique CIDR for the host node")
152 )
153
154
155 func HostCIDRFromClient(ctx context.Context, client client.Reader) (string, error) {
156 hostname, err := ien.GetHostname()
157 if err != nil {
158 return "", err
159 }
160 node := corev1.Node{}
161 if err := client.Get(ctx, types.NamespacedName{Name: hostname}, &node); err != nil {
162 return "", err
163 }
164 cidrs, err := calico.ParseNodeCIDRs(node)
165 if err != nil {
166 return "", err
167 }
168 if len(cidrs) != 1 {
169 return "", ErrNodeCIDRNotFound
170 }
171 return cidrs[0].String(), nil
172 }
173
View as plain text