Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ingress): fallback to status host if defined #446

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 40 additions & 20 deletions pkg/kube/wrappers/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,50 +72,70 @@ func (iw *IngressWrapper) GetURL() string {
return parsedURL.String()
}

if !iw.rulesExist() {
logger.Warn("No rules exist in ingress: ", iw.ingress.GetName())
return ""
}

var url string

if host, exists := iw.tryGetTLSHost(); exists { // Get TLS Host if it exists
url = host
if host, exists := iw.tryGetTLSHost(); exists { // Get TLS Host if defined
url = "https://" + host
} else if host, exists := iw.tryGetRuleHost(); exists { // Fallback to normal host if defined
url = "http://" + host
} else if host, exists := iw.tryGetStatusHost(); exists { // Fallback to status host if defined
url = "http://" + host
} else {
url = iw.getHost() // Fallback for normal Host
logger.Warn("Unable to infer host for ingress: ", iw.ingress.GetName())
return ""
}

// Append port + ingressSubPath
// Append path if defined
url += iw.getIngressSubPath()

return url
}

func (iw *IngressWrapper) rulesExist() bool {
return len(iw.ingress.Spec.Rules) > 0
func (iw *IngressWrapper) supportsTLS() bool {
return len(iw.ingress.Spec.TLS) > 0
}

func (iw *IngressWrapper) tryGetTLSHost() (string, bool) {
if iw.supportsTLS() && len(iw.ingress.Spec.TLS[0].Hosts) > 0 {
return "https://" + iw.ingress.Spec.TLS[0].Hosts[0], true
return iw.ingress.Spec.TLS[0].Hosts[0], true
}
return "", false
}

func (iw *IngressWrapper) rulesExist() bool {
return len(iw.ingress.Spec.Rules) > 0
}

func (iw *IngressWrapper) tryGetRuleHost() (string, bool) {
if iw.rulesExist() && iw.ingress.Spec.Rules[0].Host != "" {
return iw.ingress.Spec.Rules[0].Host, true
}
return "", false
}

func (iw *IngressWrapper) supportsTLS() bool {
return len(iw.ingress.Spec.TLS) > 0
func (iw *IngressWrapper) statusLoadBalancerExist() bool {
return len(iw.ingress.Status.LoadBalancer.Ingress) > 0
}

func (iw *IngressWrapper) getHost() string {
return "http://" + iw.ingress.Spec.Rules[0].Host
func (iw *IngressWrapper) tryGetStatusHost() (string, bool) {
if iw.statusLoadBalancerExist() {
ingressStatus := iw.ingress.Status.LoadBalancer.Ingress[0]
if ingressStatus.Hostname != "" {
return ingressStatus.Hostname, true
} else if ingressStatus.IP != "" {
return ingressStatus.IP, true
}
}
return "", false
}

func (iw *IngressWrapper) getIngressSubPath() string {
rule := iw.ingress.Spec.Rules[0]
if rule.HTTP != nil {
if len(rule.HTTP.Paths) > 0 {
return rule.HTTP.Paths[0].Path
if iw.rulesExist() {
rule := iw.ingress.Spec.Rules[0]
if rule.HTTP != nil {
if len(rule.HTTP.Paths) > 0 {
return rule.HTTP.Paths[0].Path
}
}
}
return ""
Expand Down
88 changes: 80 additions & 8 deletions pkg/kube/wrappers/ingress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ func TestIngressWrapper_GetURL(t *testing.T) {
{
name: "IngressWithTLSHostButNoHost",
fields: fields{
ingress: testutil.CreateIngressWithTLSHost("someIngress2", "https://google.com"),
ingress: testutil.CreateIngressWithTLSHost("someIngress2", "google.com"),
},
want: "",
want: "https://google.com",
},
{
name: "IngressWithTLSHostAndNormalHost",
Expand Down Expand Up @@ -199,6 +199,20 @@ func TestIngressWrapper_GetURL(t *testing.T) {
},
want: "",
},
{
name: "IngressWithStatusHostnameHostButNoHostNorTLSHost",
fields: fields{
ingress: testutil.CreateIngressWithStatusHostnameHost("someIngress2", "google.com"),
},
want: "http://google.com",
},
{
name: "IngressWithStatusIPHostButNoHostNorTLSHost",
fields: fields{
ingress: testutil.CreateIngressWithStatusIPHost("someIngress2", "1.1.1.1"),
},
want: "http://1.1.1.1",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -271,7 +285,7 @@ func TestIngressWrapper_tryGetTLSHost(t *testing.T) {
fields: fields{
ingress: testutil.CreateIngressWithHostAndTLSHost("someIngress", "google.com", "google.com"),
},
want: "https://google.com",
want: "google.com",
want1: true,
},
{
Expand Down Expand Up @@ -335,37 +349,95 @@ func TestIngressWrapper_supportsTLS(t *testing.T) {
}
}

func TestIngressWrapper_getHost(t *testing.T) {
func TestIngressWrapper_tryGetRuleHost(t *testing.T) {
type fields struct {
ingress *v1.Ingress
}
tests := []struct {
name string
fields fields
want string
want1 bool
}{
{
name: "IngressWithEmptyHost",
fields: fields{
ingress: testutil.CreateIngressWithHost("someIngress", ""),
},
want: "http://",
want: "",
want1: false,
},
{
name: "IngressWithCorrectHost",
fields: fields{
ingress: testutil.CreateIngressWithHost("someIngress", "google.com"),
},
want: "http://google.com",
want: "google.com",
want1: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
iw := &IngressWrapper{
ingress: tt.fields.ingress,
}
if got := iw.getHost(); got != tt.want {
t.Errorf("IngressWrapper.getHost() = %v, want %v", got, tt.want)
got, got1 := iw.tryGetRuleHost()
if got != tt.want {
t.Errorf("IngressWrapper.tryGetRuleHost() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("IngressWrapper.tryGetRuleHost() got1 = %v, want %v", got1, tt.want1)
}
})
}
}

func TestIngressWrapper_tryGetStatusHost(t *testing.T) {
type fields struct {
ingress *v1.Ingress
}
tests := []struct {
name string
fields fields
want string
want1 bool
}{
{
name: "IngressWithEmptyStatusHost",
fields: fields{
ingress: testutil.CreateIngressWithHost("someIngress", ""),
},
want: "",
want1: false,
},
{
name: "IngressWithCorrectHostnameStatusHost",
fields: fields{
ingress: testutil.CreateIngressWithStatusHostnameHost("someIngress", "google.com"),
},
want: "google.com",
want1: true,
},
{
name: "IngressWithCorrectIPStatusHost",
fields: fields{
ingress: testutil.CreateIngressWithStatusIPHost("someIngress", "1.1.1.1"),
},
want: "1.1.1.1",
want1: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
iw := &IngressWrapper{
ingress: tt.fields.ingress,
}
got, got1 := iw.tryGetStatusHost()
if got != tt.want {
t.Errorf("IngressWrapper.tryGetStatusHost() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("IngressWrapper.tryGetStatusHost() got1 = %v, want %v", got1, tt.want1)
}
})
}
Expand Down
22 changes: 22 additions & 0 deletions pkg/testutil/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,28 @@ func CreateIngressWithHostAndEmptyTLSHost(name string, host string) *v1.Ingress
return ingress
}

func CreateIngressWithStatusHostnameHost(name string, host string) *v1.Ingress {
ingress := CreateIngress(name)
ingress.Status.LoadBalancer.Ingress = []v1.IngressLoadBalancerIngress{
{
Hostname: host,
},
}

return ingress
}

func CreateIngressWithStatusIPHost(name string, host string) *v1.Ingress {
ingress := CreateIngress(name)
ingress.Status.LoadBalancer.Ingress = []v1.IngressLoadBalancerIngress{
{
IP: host,
},
}

return ingress
}

func CreateForecastleApp(name string, url string, group string, icon string) *v1alpha1.ForecastleApp {
return &v1alpha1.ForecastleApp{
ObjectMeta: metav1.ObjectMeta{
Expand Down
Loading