2016-11-10 22:56:29 +00:00
|
|
|
/*
|
|
|
|
Copyright 2015 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 status
|
|
|
|
|
|
|
|
import (
|
2020-03-24 13:44:13 +00:00
|
|
|
"context"
|
2017-04-16 18:48:12 +00:00
|
|
|
"fmt"
|
2016-12-16 17:37:47 +00:00
|
|
|
"net"
|
2021-02-26 21:57:54 +00:00
|
|
|
"regexp"
|
2016-11-10 22:56:29 +00:00
|
|
|
"sort"
|
2017-09-19 23:39:29 +00:00
|
|
|
"strings"
|
2016-11-10 22:56:29 +00:00
|
|
|
"time"
|
|
|
|
|
2020-08-08 23:31:02 +00:00
|
|
|
"k8s.io/klog/v2"
|
2016-11-10 22:56:29 +00:00
|
|
|
|
2017-09-19 23:39:29 +00:00
|
|
|
pool "gopkg.in/go-playground/pool.v3"
|
2017-09-17 18:42:31 +00:00
|
|
|
apiv1 "k8s.io/api/core/v1"
|
2023-02-16 14:05:40 +00:00
|
|
|
v1 "k8s.io/api/networking/v1"
|
2017-09-17 18:42:31 +00:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2017-04-01 14:39:42 +00:00
|
|
|
"k8s.io/apimachinery/pkg/labels"
|
2018-06-23 13:10:27 +00:00
|
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
2017-04-01 14:39:42 +00:00
|
|
|
clientset "k8s.io/client-go/kubernetes"
|
|
|
|
|
2017-11-07 22:02:12 +00:00
|
|
|
"k8s.io/ingress-nginx/internal/k8s"
|
|
|
|
"k8s.io/ingress-nginx/internal/task"
|
2022-07-22 00:32:48 +00:00
|
|
|
"k8s.io/ingress-nginx/pkg/apis/ingress"
|
2016-11-10 22:56:29 +00:00
|
|
|
)
|
|
|
|
|
2020-02-10 19:52:50 +00:00
|
|
|
// UpdateInterval defines the time interval, in seconds, in
|
|
|
|
// which the status should check if an update is required.
|
|
|
|
var UpdateInterval = 60
|
2016-11-10 22:56:29 +00:00
|
|
|
|
2023-08-31 07:36:48 +00:00
|
|
|
// Syncer is an interface that implements syncer
|
2019-03-08 00:20:34 +00:00
|
|
|
type Syncer interface {
|
|
|
|
Run(chan struct{})
|
|
|
|
|
2016-11-10 22:56:29 +00:00
|
|
|
Shutdown()
|
|
|
|
}
|
|
|
|
|
2018-01-18 19:14:42 +00:00
|
|
|
type ingressLister interface {
|
|
|
|
// ListIngresses returns the list of Ingresses
|
2020-09-25 21:45:13 +00:00
|
|
|
ListIngresses() []*ingress.Ingress
|
2018-01-18 19:14:42 +00:00
|
|
|
}
|
|
|
|
|
2023-08-31 07:36:48 +00:00
|
|
|
// Config is a structure that implements Client interfaces
|
2016-11-10 22:56:29 +00:00
|
|
|
type Config struct {
|
2017-09-18 23:53:26 +00:00
|
|
|
Client clientset.Interface
|
|
|
|
|
2016-11-10 22:56:29 +00:00
|
|
|
PublishService string
|
2017-06-20 01:22:08 +00:00
|
|
|
|
2018-02-27 03:02:19 +00:00
|
|
|
PublishStatusAddress string
|
|
|
|
|
2017-06-20 01:22:08 +00:00
|
|
|
UpdateStatusOnShutdown bool
|
2017-03-09 22:08:26 +00:00
|
|
|
|
2017-10-08 17:29:19 +00:00
|
|
|
UseNodeInternalIP bool
|
|
|
|
|
2018-01-18 19:14:42 +00:00
|
|
|
IngressLister ingressLister
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// statusSync keeps the status IP in each Ingress rule updated executing a periodic check
|
|
|
|
// in all the defined rules. To simplify the process leader election is used so the update
|
|
|
|
// is executed only in one node (Ingress controllers can be scaled to more than one)
|
|
|
|
// If the controller is running with the flag --publish-service (with a valid service)
|
2018-02-27 03:02:19 +00:00
|
|
|
// the IP address behind the service is used, if it is running with the flag
|
|
|
|
// --publish-status-address, the address specified in the flag is used, if neither of the
|
|
|
|
// two flags are set, the source is the IP/s of the node/s
|
2016-11-10 22:56:29 +00:00
|
|
|
type statusSync struct {
|
|
|
|
Config
|
2019-03-08 00:20:34 +00:00
|
|
|
|
2016-11-10 22:56:29 +00:00
|
|
|
// workqueue used to keep in sync the status IP/s
|
|
|
|
// in the Ingress rules
|
|
|
|
syncQueue *task.Queue
|
|
|
|
}
|
|
|
|
|
2019-03-08 00:20:34 +00:00
|
|
|
// Start starts the loop to keep the status in sync
|
2023-08-31 07:36:48 +00:00
|
|
|
func (s *statusSync) Run(stopCh chan struct{}) {
|
2019-03-08 00:20:34 +00:00
|
|
|
go s.syncQueue.Run(time.Second, stopCh)
|
2018-10-29 16:01:41 +00:00
|
|
|
|
2019-03-08 00:20:34 +00:00
|
|
|
// trigger initial sync
|
|
|
|
s.syncQueue.EnqueueTask(task.GetDummyObject("sync status"))
|
2018-10-29 16:01:41 +00:00
|
|
|
|
2019-03-08 00:20:34 +00:00
|
|
|
// when this instance is the leader we need to enqueue
|
|
|
|
// an item to trigger the update of the Ingress status.
|
2023-08-31 07:36:48 +00:00
|
|
|
//nolint:staticcheck // TODO: will replace it since wait.PollUntil is deprecated
|
2023-07-03 12:50:52 +00:00
|
|
|
err := wait.PollUntil(time.Duration(UpdateInterval)*time.Second, func() (bool, error) {
|
2019-03-08 00:20:34 +00:00
|
|
|
s.syncQueue.EnqueueTask(task.GetDummyObject("sync status"))
|
|
|
|
return false, nil
|
|
|
|
}, stopCh)
|
2023-07-03 12:50:52 +00:00
|
|
|
if err != nil {
|
|
|
|
klog.ErrorS(err, "error running poll")
|
|
|
|
}
|
2017-08-15 21:34:36 +00:00
|
|
|
}
|
|
|
|
|
2019-03-08 00:20:34 +00:00
|
|
|
// Shutdown stops the sync. In case the instance is the leader it will remove the current IP
|
2016-11-10 22:56:29 +00:00
|
|
|
// if there is no other instances running.
|
2023-08-31 07:36:48 +00:00
|
|
|
func (s *statusSync) Shutdown() {
|
2016-11-10 22:56:29 +00:00
|
|
|
go s.syncQueue.Shutdown()
|
2018-10-29 16:01:41 +00:00
|
|
|
|
2017-06-20 01:22:08 +00:00
|
|
|
if !s.UpdateStatusOnShutdown {
|
2018-12-05 16:27:55 +00:00
|
|
|
klog.Warningf("skipping update of status of Ingress rules")
|
2017-06-20 01:22:08 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-07-14 13:30:58 +00:00
|
|
|
addrs, err := s.runningAddresses()
|
2016-11-10 22:56:29 +00:00
|
|
|
if err != nil {
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.ErrorS(err, "error obtaining running IP address")
|
2016-11-10 22:56:29 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-12-16 17:37:47 +00:00
|
|
|
if len(addrs) > 1 {
|
2016-11-10 22:56:29 +00:00
|
|
|
// leave the job to the next leader
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.InfoS("leaving status update for next leader")
|
2016-11-10 22:56:29 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:14:20 +00:00
|
|
|
if s.isRunningMultiplePods() {
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.V(2).InfoS("skipping Ingress status update (multiple pods running - another one will be elected as master)")
|
2017-04-09 19:14:20 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.InfoS("removing value from ingress status", "address", addrs)
|
2023-01-18 13:10:34 +00:00
|
|
|
s.updateStatus([]v1.IngressLoadBalancerIngress{})
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
|
|
|
|
2023-08-31 07:36:48 +00:00
|
|
|
func (s *statusSync) sync(_ interface{}) error {
|
2017-03-31 12:46:51 +00:00
|
|
|
if s.syncQueue.IsShuttingDown() {
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.V(2).InfoS("skipping Ingress status update (shutting down in progress)")
|
2017-03-31 12:46:51 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-07-14 13:30:58 +00:00
|
|
|
addrs, err := s.runningAddresses()
|
2016-11-10 22:56:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-09-07 17:41:16 +00:00
|
|
|
s.updateStatus(standardizeLoadBalancerIngresses(addrs))
|
2016-11-10 22:56:29 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-08-31 07:36:48 +00:00
|
|
|
func (s *statusSync) keyfunc(input interface{}) (interface{}, error) {
|
2016-11-10 22:56:29 +00:00
|
|
|
return input, nil
|
|
|
|
}
|
|
|
|
|
2019-03-08 00:20:34 +00:00
|
|
|
// NewStatusSyncer returns a new Syncer instance
|
2020-09-26 23:27:19 +00:00
|
|
|
func NewStatusSyncer(config Config) Syncer {
|
2023-08-31 07:36:48 +00:00
|
|
|
st := &statusSync{
|
2017-09-11 21:56:20 +00:00
|
|
|
Config: config,
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
|
|
|
st.syncQueue = task.NewCustomTaskQueue(st.sync, st.keyfunc)
|
|
|
|
|
|
|
|
return st
|
|
|
|
}
|
|
|
|
|
2023-01-18 13:10:34 +00:00
|
|
|
func nameOrIPToLoadBalancerIngress(nameOrIP string) v1.IngressLoadBalancerIngress {
|
2021-09-07 17:41:16 +00:00
|
|
|
if net.ParseIP(nameOrIP) != nil {
|
2023-01-18 13:10:34 +00:00
|
|
|
return v1.IngressLoadBalancerIngress{IP: nameOrIP}
|
2021-09-07 17:41:16 +00:00
|
|
|
}
|
|
|
|
|
2023-01-18 13:10:34 +00:00
|
|
|
return v1.IngressLoadBalancerIngress{Hostname: nameOrIP}
|
2021-09-07 17:41:16 +00:00
|
|
|
}
|
|
|
|
|
2017-07-14 13:30:58 +00:00
|
|
|
// runningAddresses returns a list of IP addresses and/or FQDN where the
|
2016-12-16 17:37:47 +00:00
|
|
|
// ingress controller is currently running
|
2023-01-18 13:10:34 +00:00
|
|
|
func (s *statusSync) runningAddresses() ([]v1.IngressLoadBalancerIngress, error) {
|
2019-08-25 16:27:34 +00:00
|
|
|
if s.PublishStatusAddress != "" {
|
2021-02-26 21:57:54 +00:00
|
|
|
re := regexp.MustCompile(`,\s*`)
|
|
|
|
multipleAddrs := re.Split(s.PublishStatusAddress, -1)
|
2023-01-18 13:10:34 +00:00
|
|
|
addrs := make([]v1.IngressLoadBalancerIngress, len(multipleAddrs))
|
2021-09-07 17:41:16 +00:00
|
|
|
for i, addr := range multipleAddrs {
|
|
|
|
addrs[i] = nameOrIPToLoadBalancerIngress(addr)
|
|
|
|
}
|
|
|
|
return addrs, nil
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
|
|
|
|
2019-08-25 16:27:34 +00:00
|
|
|
if s.PublishService != "" {
|
|
|
|
return statusAddressFromService(s.PublishService, s.Client)
|
2018-02-27 03:02:19 +00:00
|
|
|
}
|
|
|
|
|
2016-11-10 22:56:29 +00:00
|
|
|
// get information about all the pods running the ingress controller
|
2020-11-14 02:40:28 +00:00
|
|
|
pods, err := s.Client.CoreV1().Pods(k8s.IngressPodDetails.Namespace).List(context.TODO(), metav1.ListOptions{
|
|
|
|
LabelSelector: labels.SelectorFromSet(k8s.IngressPodDetails.Labels).String(),
|
2016-11-10 22:56:29 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-01-18 13:10:34 +00:00
|
|
|
addrs := make([]v1.IngressLoadBalancerIngress, 0)
|
2020-12-04 12:40:42 +00:00
|
|
|
for i := range pods.Items {
|
|
|
|
pod := pods.Items[i]
|
2018-02-15 05:19:27 +00:00
|
|
|
// only Running pods are valid
|
|
|
|
if pod.Status.Phase != apiv1.PodRunning {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-10-12 23:22:16 +00:00
|
|
|
// only Ready pods are valid
|
|
|
|
isPodReady := false
|
|
|
|
for _, cond := range pod.Status.Conditions {
|
|
|
|
if cond.Type == apiv1.PodReady && cond.Status == apiv1.ConditionTrue {
|
|
|
|
isPodReady = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !isPodReady {
|
|
|
|
klog.InfoS("POD is not ready", "pod", klog.KObj(&pod), "node", pod.Spec.NodeName)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-11-06 01:22:49 +00:00
|
|
|
name := k8s.GetNodeIPOrName(s.Client, pod.Spec.NodeName, s.UseNodeInternalIP)
|
2021-09-07 17:41:16 +00:00
|
|
|
if !stringInIngresses(name, addrs) {
|
|
|
|
addrs = append(addrs, nameOrIPToLoadBalancerIngress(name))
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
|
|
|
}
|
2017-11-06 01:22:49 +00:00
|
|
|
|
2016-12-16 17:56:27 +00:00
|
|
|
return addrs, nil
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
|
|
|
|
2017-04-09 19:14:20 +00:00
|
|
|
func (s *statusSync) isRunningMultiplePods() bool {
|
2021-09-30 04:10:09 +00:00
|
|
|
// As a standard, app.kubernetes.io are "reserved well-known" labels.
|
|
|
|
// In our case, we add those labels as identifiers of the Ingress
|
|
|
|
// deployment in this namespace, so we can select it as a set of Ingress instances.
|
|
|
|
// As those labels are also generated as part of a HELM deployment, we can be "safe" they
|
|
|
|
// cover 95% of the cases
|
|
|
|
podLabel := make(map[string]string)
|
|
|
|
for k, v := range k8s.IngressPodDetails.Labels {
|
|
|
|
if k != "pod-template-hash" && k != "controller-revision-hash" && k != "pod-template-generation" {
|
|
|
|
podLabel[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-14 02:40:28 +00:00
|
|
|
pods, err := s.Client.CoreV1().Pods(k8s.IngressPodDetails.Namespace).List(context.TODO(), metav1.ListOptions{
|
2021-09-30 04:10:09 +00:00
|
|
|
LabelSelector: labels.SelectorFromSet(podLabel).String(),
|
2017-04-09 19:14:20 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return len(pods.Items) > 1
|
|
|
|
}
|
|
|
|
|
2021-09-07 17:41:16 +00:00
|
|
|
// standardizeLoadBalancerIngresses sorts the list of loadbalancer by
|
|
|
|
// IP
|
2023-01-18 13:10:34 +00:00
|
|
|
func standardizeLoadBalancerIngresses(lbi []v1.IngressLoadBalancerIngress) []v1.IngressLoadBalancerIngress {
|
2017-09-25 19:40:55 +00:00
|
|
|
sort.SliceStable(lbi, func(a, b int) bool {
|
2017-09-18 23:53:26 +00:00
|
|
|
return lbi[a].IP < lbi[b].IP
|
|
|
|
})
|
|
|
|
|
2016-11-10 22:56:29 +00:00
|
|
|
return lbi
|
|
|
|
}
|
|
|
|
|
2017-07-28 22:57:33 +00:00
|
|
|
// updateStatus changes the status information of Ingress rules
|
2023-01-18 13:10:34 +00:00
|
|
|
func (s *statusSync) updateStatus(newIngressPoint []v1.IngressLoadBalancerIngress) {
|
2020-09-25 21:45:13 +00:00
|
|
|
ings := s.IngressLister.ListIngresses()
|
2017-09-19 23:39:29 +00:00
|
|
|
|
|
|
|
p := pool.NewLimited(10)
|
|
|
|
defer p.Close()
|
|
|
|
|
|
|
|
batch := p.Batch()
|
2018-10-19 02:57:01 +00:00
|
|
|
sort.SliceStable(newIngressPoint, lessLoadBalancerIngress(newIngressPoint))
|
2017-09-19 23:39:29 +00:00
|
|
|
|
2018-01-18 19:14:42 +00:00
|
|
|
for _, ing := range ings {
|
2018-10-29 16:01:41 +00:00
|
|
|
curIPs := ing.Status.LoadBalancer.Ingress
|
|
|
|
sort.SliceStable(curIPs, lessLoadBalancerIngress(curIPs))
|
|
|
|
if ingressSliceEqual(curIPs, newIngressPoint) {
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.V(3).InfoS("skipping update of Ingress (no change)", "namespace", ing.Namespace, "ingress", ing.Name)
|
2018-10-29 16:01:41 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-11-05 01:18:28 +00:00
|
|
|
batch.Queue(runUpdate(ing, newIngressPoint, s.Client))
|
2017-09-19 23:39:29 +00:00
|
|
|
}
|
2016-11-10 22:56:29 +00:00
|
|
|
|
2017-09-19 23:39:29 +00:00
|
|
|
batch.QueueComplete()
|
|
|
|
batch.WaitAll()
|
|
|
|
}
|
2017-07-28 22:57:33 +00:00
|
|
|
|
2023-01-18 13:10:34 +00:00
|
|
|
func runUpdate(ing *ingress.Ingress, status []v1.IngressLoadBalancerIngress,
|
2023-08-31 07:36:48 +00:00
|
|
|
client clientset.Interface,
|
|
|
|
) pool.WorkFunc {
|
2017-09-19 23:39:29 +00:00
|
|
|
return func(wu pool.WorkUnit) (interface{}, error) {
|
|
|
|
if wu.IsCancelled() {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2017-09-18 23:53:26 +00:00
|
|
|
|
2021-08-21 20:42:00 +00:00
|
|
|
ingClient := client.NetworkingV1().Ingresses(ing.Namespace)
|
2020-09-02 13:08:53 +00:00
|
|
|
currIng, err := ingClient.Get(context.TODO(), ing.Name, metav1.GetOptions{})
|
|
|
|
if err != nil {
|
2022-01-10 00:29:12 +00:00
|
|
|
return nil, fmt.Errorf("unexpected error searching Ingress %s/%s: %w", ing.Namespace, ing.Name, err)
|
2020-09-02 13:08:53 +00:00
|
|
|
}
|
|
|
|
|
2020-09-27 20:32:40 +00:00
|
|
|
klog.InfoS("updating Ingress status", "namespace", currIng.Namespace, "ingress", currIng.Name, "currentValue", currIng.Status.LoadBalancer.Ingress, "newValue", status)
|
2020-09-02 13:08:53 +00:00
|
|
|
currIng.Status.LoadBalancer.Ingress = status
|
|
|
|
_, err = ingClient.UpdateStatus(context.TODO(), currIng, metav1.UpdateOptions{})
|
|
|
|
if err != nil {
|
|
|
|
klog.Warningf("error updating ingress rule: %v", err)
|
2017-09-19 23:39:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true, nil
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
2017-09-19 23:39:29 +00:00
|
|
|
}
|
2016-11-10 22:56:29 +00:00
|
|
|
|
2023-01-18 13:10:34 +00:00
|
|
|
func lessLoadBalancerIngress(addrs []v1.IngressLoadBalancerIngress) func(int, int) bool {
|
2017-09-19 23:39:29 +00:00
|
|
|
return func(a, b int) bool {
|
|
|
|
switch strings.Compare(addrs[a].Hostname, addrs[b].Hostname) {
|
|
|
|
case -1:
|
|
|
|
return true
|
|
|
|
case 1:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return addrs[a].IP < addrs[b].IP
|
|
|
|
}
|
2016-11-10 22:56:29 +00:00
|
|
|
}
|
|
|
|
|
2023-01-18 13:10:34 +00:00
|
|
|
func ingressSliceEqual(lhs, rhs []v1.IngressLoadBalancerIngress) bool {
|
2016-11-10 22:56:29 +00:00
|
|
|
if len(lhs) != len(rhs) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range lhs {
|
|
|
|
if lhs[i].IP != rhs[i].IP {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if lhs[i].Hostname != rhs[i].Hostname {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2018-10-29 16:01:41 +00:00
|
|
|
|
2016-11-10 22:56:29 +00:00
|
|
|
return true
|
|
|
|
}
|
2019-08-25 16:27:34 +00:00
|
|
|
|
2023-01-18 13:10:34 +00:00
|
|
|
func statusAddressFromService(service string, kubeClient clientset.Interface) ([]v1.IngressLoadBalancerIngress, error) {
|
2023-08-31 07:36:48 +00:00
|
|
|
ns, name, err := k8s.ParseNameNS(service)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-03-24 13:44:13 +00:00
|
|
|
svc, err := kubeClient.CoreV1().Services(ns).Get(context.TODO(), name, metav1.GetOptions{})
|
2019-08-25 16:27:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
switch svc.Spec.Type {
|
|
|
|
case apiv1.ServiceTypeExternalName:
|
2023-01-18 13:10:34 +00:00
|
|
|
return []v1.IngressLoadBalancerIngress{{
|
2021-09-07 17:41:16 +00:00
|
|
|
Hostname: svc.Spec.ExternalName,
|
|
|
|
}}, nil
|
2019-08-25 16:27:34 +00:00
|
|
|
case apiv1.ServiceTypeClusterIP:
|
2023-01-18 13:10:34 +00:00
|
|
|
return []v1.IngressLoadBalancerIngress{{
|
2021-09-07 17:41:16 +00:00
|
|
|
IP: svc.Spec.ClusterIP,
|
|
|
|
}}, nil
|
2019-08-25 16:27:34 +00:00
|
|
|
case apiv1.ServiceTypeNodePort:
|
2021-09-07 17:41:16 +00:00
|
|
|
if svc.Spec.ExternalIPs == nil {
|
2023-01-18 13:10:34 +00:00
|
|
|
return []v1.IngressLoadBalancerIngress{{
|
2021-09-07 17:41:16 +00:00
|
|
|
IP: svc.Spec.ClusterIP,
|
|
|
|
}}, nil
|
|
|
|
}
|
2023-08-31 07:36:48 +00:00
|
|
|
addrs := make([]v1.IngressLoadBalancerIngress, 0, len(svc.Spec.ExternalIPs))
|
|
|
|
for _, ip := range svc.Spec.ExternalIPs {
|
|
|
|
addrs = append(addrs, v1.IngressLoadBalancerIngress{IP: ip})
|
2019-10-21 04:23:27 +00:00
|
|
|
}
|
2021-09-07 17:41:16 +00:00
|
|
|
return addrs, nil
|
2019-08-25 16:27:34 +00:00
|
|
|
case apiv1.ServiceTypeLoadBalancer:
|
2023-08-31 07:36:48 +00:00
|
|
|
addrs := make([]v1.IngressLoadBalancerIngress, 0, len(svc.Status.LoadBalancer.Ingress))
|
2021-09-07 17:41:16 +00:00
|
|
|
for i, ingress := range svc.Status.LoadBalancer.Ingress {
|
2023-08-31 07:36:48 +00:00
|
|
|
addrs = append(addrs, v1.IngressLoadBalancerIngress{})
|
2021-09-07 17:41:16 +00:00
|
|
|
if ingress.Hostname != "" {
|
|
|
|
addrs[i].Hostname = ingress.Hostname
|
|
|
|
}
|
|
|
|
if ingress.IP != "" {
|
|
|
|
addrs[i].IP = ingress.IP
|
2019-08-25 16:27:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-07 17:41:16 +00:00
|
|
|
for _, ip := range svc.Spec.ExternalIPs {
|
|
|
|
if !stringInIngresses(ip, addrs) {
|
2023-01-18 13:10:34 +00:00
|
|
|
addrs = append(addrs, v1.IngressLoadBalancerIngress{IP: ip})
|
2021-09-07 17:41:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return addrs, nil
|
2019-08-25 16:27:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil, fmt.Errorf("unable to extract IP address/es from service %v", service)
|
|
|
|
}
|
2020-10-26 14:24:55 +00:00
|
|
|
|
2024-04-19 09:25:09 +00:00
|
|
|
// stringInIngresses returns true if s is in list
|
2023-01-18 13:10:34 +00:00
|
|
|
func stringInIngresses(s string, list []v1.IngressLoadBalancerIngress) bool {
|
2020-10-26 14:24:55 +00:00
|
|
|
for _, v := range list {
|
2021-09-07 17:41:16 +00:00
|
|
|
if v.IP == s || v.Hostname == s {
|
2020-10-26 14:24:55 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|