-
Notifications
You must be signed in to change notification settings - Fork 296
/
init.go
133 lines (111 loc) · 4.14 KB
/
init.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
Copyright 2017 The Kubernetes Authors.
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 app
import (
"context"
"fmt"
"time"
v1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/ingress-gce/pkg/flags"
"k8s.io/ingress-gce/pkg/utils"
"k8s.io/klog/v2"
)
// DefaultBackendServicePort returns the ServicePort which will be
// used as the default backend for load balancers.
func DefaultBackendServicePort(kubeClient kubernetes.Interface, logger klog.Logger) utils.ServicePort {
if flags.F.DefaultSvc == "" {
klog.Fatalf("Please specify --default-backend-service")
}
if flags.F.DefaultSvcPortName == "" {
klog.Fatalf("Please specify --default-backend-service-port")
}
name, err := utils.ToNamespacedName(flags.F.DefaultSvc)
if err != nil {
klog.Fatalf("Failed to parse --default-backend-service: %v", err)
}
svc, err := waitForServicePort(kubeClient, name, flags.F.DefaultSvcPortName, logger)
if err != nil {
klog.Fatalf("Failed to verify default backend service: %v", err)
}
svcPort := servicePortForDefaultService(svc, flags.F.DefaultSvcPortName, name)
if svcPort == nil {
klog.Fatalf("could not derive service port for default service: %v", err)
}
return *svcPort
}
// IngressClassEnabled returns whether the IngressClass API exists on the kubernetes cluster
func IngressClassEnabled(client kubernetes.Interface, logger klog.Logger) bool {
logger.V(2).Info("Checking if Ingress Class API exists")
err := wait.Poll(3*time.Second, 5*time.Minute, func() (bool, error) {
resourceList, err := client.Discovery().ServerResourcesForGroupVersion("networking.k8s.io/v1")
if err != nil {
logger.Error(err, "Errored checking for Ingress Class API")
return false, nil
}
for _, resource := range resourceList.APIResources {
if resource.Name == "ingressclasses" {
return true, nil
}
}
return true, fmt.Errorf("Ingress Class API is not supported")
})
if err != nil {
logger.V(2).Info("Ingress Class support disabled. Received error while checking for Ingress Class API", "err", err)
return false
}
logger.V(2).Info("Ingress Class support enabled")
return true
}
// servicePortForDefaultService returns the service port for the default service; returns nil if not found.
func servicePortForDefaultService(svc *v1.Service, svcPortName string, name types.NamespacedName) *utils.ServicePort {
// Lookup TargetPort for service port
for _, port := range svc.Spec.Ports {
if port.Name == svcPortName {
return &utils.ServicePort{
ID: utils.ServicePortID{
Service: name,
Port: networkingv1.ServiceBackendPort{Name: svcPortName},
},
TargetPort: port.TargetPort,
Port: port.Port,
PortName: port.Name,
}
}
}
return nil
}
// servicePortExists checks that the service and specified port name exists.
func waitForServicePort(client kubernetes.Interface, name types.NamespacedName, portName string, logger klog.Logger) (*v1.Service, error) {
logger.V(2).Info("Checking existence of default backend service", "serviceKey", name.String())
var svc *v1.Service
err := wait.Poll(3*time.Second, 5*time.Minute, func() (bool, error) {
var err error
svc, err = client.CoreV1().Services(name.Namespace).Get(context.TODO(), name.Name, meta_v1.GetOptions{})
if err != nil {
logger.V(4).Info("Error getting service", "serviceKey", name.String())
return false, nil
}
for _, p := range svc.Spec.Ports {
if p.Name == portName {
return true, nil
}
}
return false, fmt.Errorf("port %q not found in service %q", portName, name.String())
})
return svc, err
}