func (a *Adapter) ListRoutegroups() ([]*Ingress, error) {
	rgs, err := listRoutegroups(a.kubeClient)
	if err != nil {
		return nil, err
	}
	var ret []*Ingress
	for _, rg := range rgs.Items {
		if !a.supportedRoutegroup(rg.Metadata) {
			continue
		}
		ing, err := a.newIngressFromRouteGroup(rg)
		if err == nil {
			ret = append(ret, ing)
		} else {
			log.WithFields(log.Fields{
				"type": ingressTypeRouteGroup.String(),
				"ns":   rg.Metadata.Namespace,
				"name": rg.Metadata.Name,
			}).Errorf("%v", err)
		}
	}
	return ret, nil
}
ListRoutegroups can be used to obtain the list of Ingress resources
for all namespaces filtered by class. It returns the Ingress
business object, that for the controller does not matter to be
routegroup or ingress.
package kubernetes
import (
	"errors"
	"fmt"
	"strings"
	"github.com/aws/aws-sdk-go/service/elbv2"
	log "github.com/sirupsen/logrus"
	"github.com/zalando-incubator/kube-ingress-aws-controller/aws"
)
type Adapter struct {
	kubeClient                     client
	ingressClient                  *ingressClient
	ingressFilters                 []string
	ingressDefaultSecurityGroup    string
	ingressDefaultSSLPolicy        string
	ingressDefaultLoadBalancerType string
	clusterLocalDomain             string
	routeGroupSupport              bool
}
type ingressType int
const (
	ingressTypeIngress ingressType = iota + 1
	ingressTypeRouteGroup
)
func (t ingressType) String() string {
	switch t {
	case ingressTypeIngress:
		return "ingress"
	case ingressTypeRouteGroup:
		return "routegroup"
	default:
		return "unknown"
	}
}
const (
	DefaultClusterLocalDomain = ".cluster.local"
	loadBalancerTypeNLB       = "nlb"
	loadBalancerTypeALB       = "alb"
)
var (
	ErrMissingKubernetesEnv = errors.New("unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and " +
		"KUBERNETES_SERVICE_PORT are not defined")
	ErrInvalidIngressUpdateParams = errors.New("invalid ingress update parameters")
	ErrInvalidIngressUpdateARNParams = errors.New("invalid ingress updateARN parameters")
	ErrUpdateNotNeeded = errors.New("update to ingress resource not needed")
	ErrInvalidConfiguration = errors.New("invalid Kubernetes Adapter configuration")
	ErrInvalidCertificates = errors.New("invalid CA certificates")
	loadBalancerTypesIngressToAWS = map[string]string{
		loadBalancerTypeALB: aws.LoadBalancerTypeApplication,
		loadBalancerTypeNLB: aws.LoadBalancerTypeNetwork,
	}
	loadBalancerTypesAWSToIngress = map[string]string{
		aws.LoadBalancerTypeApplication: loadBalancerTypeALB,
		aws.LoadBalancerTypeNetwork:     loadBalancerTypeNLB,
	}
)
type Ingress struct {
	Shared           bool
	HTTP2            bool
	ClusterLocal     bool
	CertificateARN   string
	Namespace        string
	Name             string
	Hostname         string
	Scheme           string
	SecurityGroup    string
	SSLPolicy        string
	IPAddressType    string
	LoadBalancerType string
	WAFWebACLID      string
	Hostnames        []string
	resourceType     ingressType
}
func (i *Ingress) String() string {
	return fmt.Sprintf("%s/%s", i.Namespace, i.Name)
}
type ConfigMap struct {
	Namespace string
	Name      string
	Data      map[string]string
}
func (c *ConfigMap) String() string {
	return fmt.Sprintf("%s/%s", c.Namespace, c.Name)
}
func NewAdapter(config *Config, ingressAPIVersion string, ingressClassFilters []string, ingressDefaultSecurityGroup, ingressDefaultSSLPolicy, ingressDefaultLoadBalancerType, clusterLocalDomain string, disableInstrumentedHttpClient bool) (*Adapter, error) {
	if config == nil || config.BaseURL == "" {
		return nil, ErrInvalidConfiguration
	}
	c, err := newSimpleClient(config, disableInstrumentedHttpClient)
	if err != nil {
		return nil, err
	}
	return &Adapter{
		kubeClient:                     c,
		ingressClient:                  &ingressClient{apiVersion: ingressAPIVersion},
		ingressFilters:                 ingressClassFilters,
		ingressDefaultSecurityGroup:    ingressDefaultSecurityGroup,
		ingressDefaultSSLPolicy:        ingressDefaultSSLPolicy,
		ingressDefaultLoadBalancerType: loadBalancerTypesAWSToIngress[ingressDefaultLoadBalancerType],
		clusterLocalDomain:             clusterLocalDomain,
		routeGroupSupport:              true,
	}, nil
}
func (a *Adapter) newIngressFromKube(kubeIngress *ingress) (*Ingress, error) {
	var host string
	var hostnames []string
	for _, ingressLoadBalancer := range kubeIngress.Status.LoadBalancer.Ingress {
		if ingressLoadBalancer.Hostname != "" {
			host = ingressLoadBalancer.Hostname
			break
		}
	}
	for _, rule := range kubeIngress.Spec.Rules {
		if rule.Host != "" && (a.clusterLocalDomain == "" || !strings.HasSuffix(rule.Host, a.clusterLocalDomain)) {
			hostnames = append(hostnames, rule.Host)
		}
	}
	return a.newIngress(ingressTypeIngress, kubeIngress.Metadata, host, hostnames)
}
func (a *Adapter) newIngressFromRouteGroup(rg *routegroup) (*Ingress, error) {
	var host string
	var hostnames []string
	for _, lb := range rg.Status.LoadBalancer.Routegroup {
		if lb.Hostname != "" {
			host = lb.Hostname
			break
		}
	}
	for _, host := range rg.Spec.Hosts {
		if host != "" && (a.clusterLocalDomain == "" || !strings.HasSuffix(host, a.clusterLocalDomain)) {
			hostnames = append(hostnames, host)
		}
	}
	return a.newIngress(ingressTypeRouteGroup, rg.Metadata, host, hostnames)
}
func (a *Adapter) newIngress(typ ingressType, metadata kubeItemMetadata, host string, hostnames []string) (*Ingress, error) {
	annotations := metadata.Annotations
	var scheme string
	switch getAnnotationsString(annotations, ingressSchemeAnnotation, "") {
	case elbv2.LoadBalancerSchemeEnumInternal:
		scheme = elbv2.LoadBalancerSchemeEnumInternal
	default:
		scheme = elbv2.LoadBalancerSchemeEnumInternetFacing
	}
	shared := true
	if getAnnotationsString(annotations, ingressSharedAnnotation, "") == "false" {
		shared = false
	}
	ipAddressType := aws.IPAddressTypeIPV4
	if getAnnotationsString(annotations, ingressALBIPAddressType, "") == aws.IPAddressTypeDualstack {
		ipAddressType = aws.IPAddressTypeDualstack
	}
	sslPolicy := getAnnotationsString(annotations, ingressSSLPolicyAnnotation, a.ingressDefaultSSLPolicy)
	if _, ok := aws.SSLPolicies[sslPolicy]; !ok {
		sslPolicy = a.ingressDefaultSSLPolicy
	}
	loadBalancerType, hasLB := annotations[ingressLoadBalancerTypeAnnotation]
	if !hasLB {
		loadBalancerType = a.ingressDefaultLoadBalancerType
	}
	securityGroup, hasSG := annotations[ingressSecurityGroupAnnotation]
	if !hasSG {
		securityGroup = a.ingressDefaultSecurityGroup
	}
	wafWebAclId, hasWAF := annotations[ingressWAFWebACLIDAnnotation]
	if (loadBalancerType == loadBalancerTypeNLB) && (hasSG || hasWAF) {
		if hasLB {
			return nil, errors.New("security group or WAF are not supported by NLB (configured by annotation)")
		}
		loadBalancerType = loadBalancerTypeALB
	}
	if _, ok := loadBalancerTypesIngressToAWS[loadBalancerType]; !ok {
		loadBalancerType = a.ingressDefaultLoadBalancerType
	}
	loadBalancerType = loadBalancerTypesIngressToAWS[loadBalancerType]
	if loadBalancerType == aws.LoadBalancerTypeNetwork {
		ipAddressType = aws.IPAddressTypeIPV4
	}
	http2 := true
	if getAnnotationsString(annotations, ingressHTTP2Annotation, "") == "false" {
		http2 = false
	}
	return &Ingress{
		resourceType:     typ,
		Namespace:        metadata.Namespace,
		Name:             metadata.Name,
		Hostname:         host,
		Hostnames:        hostnames,
		ClusterLocal:     len(hostnames) < 1,
		CertificateARN:   getAnnotationsString(annotations, ingressCertificateARNAnnotation, ""),
		Scheme:           scheme,
		Shared:           shared,
		SecurityGroup:    securityGroup,
		SSLPolicy:        sslPolicy,
		IPAddressType:    ipAddressType,
		LoadBalancerType: loadBalancerType,
		WAFWebACLID:      wafWebAclId,
		HTTP2:            http2,
	}, nil
}
func (a *Adapter) IngressFiltersString() string {
	return strings.TrimSpace(strings.Join(a.ingressFilters, ","))
}
func (a *Adapter) ListResources() ([]*Ingress, error) {
	ings, err := a.ListIngress()
	if err != nil {
		return nil, err
	}
	rgs, err := a.ListRoutegroups()
	if err != nil {
		if a.routeGroupSupport {
			a.routeGroupSupport = false
			log.Warnf("Disabling RouteGroup support because listing RouteGroups failed: %v, to get more information https://opensource.zalando.com/skipper/kubernetes/routegroups/#routegroups", err)
		}
		if err == ErrResourceNotFound || err == ErrNoPermissionToAccessResource {
			return ings, nil
		}
		return nil, err
	}
	a.routeGroupSupport = true
	return append(ings, rgs...), nil
}
func (a *Adapter) ListIngress() ([]*Ingress, error) {
	il, err := a.ingressClient.listIngress(a.kubeClient)
	if err != nil {
		return nil, err
	}
	var ret []*Ingress
	for _, ingress := range il.Items {
		if !a.supportedIngress(ingress) {
			continue
		}
		ing, err := a.newIngressFromKube(ingress)
		if err == nil {
			ret = append(ret, ing)
		} else {
			log.WithFields(log.Fields{
				"type": ingressTypeIngress.String(),
				"ns":   ingress.Metadata.Namespace,
				"name": ingress.Metadata.Name,
			}).Errorf("%v", err)
		}
	}
	return ret, nil
}