blob: 0dc2703d3f0e261dfb6108b049f036eb761d7a2c [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 translation
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
configv1 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v1"
apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
)
func TestTranslateUpstreamHealthCheck(t *testing.T) {
tr := &translator{}
hc := &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: apisixv1.HealthCheckHTTP,
Timeout: 5 * time.Second,
Concurrency: 2,
HTTPPath: "/healthz",
Unhealthy: &configv1.ActiveHealthCheckUnhealthy{
PassiveHealthCheckUnhealthy: configv1.PassiveHealthCheckUnhealthy{
HTTPCodes: []int{500, 502, 504},
},
Interval: metav1.Duration{Duration: time.Second},
},
Healthy: &configv1.ActiveHealthCheckHealthy{
PassiveHealthCheckHealthy: configv1.PassiveHealthCheckHealthy{
HTTPCodes: []int{200},
Successes: 2,
},
Interval: metav1.Duration{Duration: 3 * time.Second},
},
},
Passive: &configv1.PassiveHealthCheck{
Type: apisixv1.HealthCheckHTTP,
Healthy: &configv1.PassiveHealthCheckHealthy{
HTTPCodes: []int{200},
Successes: 2,
},
Unhealthy: &configv1.PassiveHealthCheckUnhealthy{
HTTPCodes: []int{500},
},
},
}
var ups apisixv1.Upstream
err := tr.translateUpstreamHealthCheck(hc, &ups)
assert.Nil(t, err, "translating upstream health check")
assert.Equal(t, ups.Checks.Active, &apisixv1.UpstreamActiveHealthCheck{
Type: apisixv1.HealthCheckHTTP,
Timeout: 5,
Concurrency: 2,
HTTPPath: "/healthz",
HTTPSVerifyCert: true,
Healthy: apisixv1.UpstreamActiveHealthCheckHealthy{
Interval: 3,
UpstreamPassiveHealthCheckHealthy: apisixv1.UpstreamPassiveHealthCheckHealthy{
HTTPStatuses: []int{200},
Successes: 2,
},
},
Unhealthy: apisixv1.UpstreamActiveHealthCheckUnhealthy{
Interval: 1,
UpstreamPassiveHealthCheckUnhealthy: apisixv1.UpstreamPassiveHealthCheckUnhealthy{
HTTPStatuses: []int{500, 502, 504},
},
},
})
assert.Equal(t, ups.Checks.Passive, &apisixv1.UpstreamPassiveHealthCheck{
Type: apisixv1.HealthCheckHTTP,
Healthy: apisixv1.UpstreamPassiveHealthCheckHealthy{
Successes: 2,
HTTPStatuses: []int{200},
},
Unhealthy: apisixv1.UpstreamPassiveHealthCheckUnhealthy{
HTTPStatuses: []int{500},
},
})
}
func TestTranslateUpstreamPassiveHealthCheckUnusually(t *testing.T) {
tr := &translator{}
// invalid passive health check type
hc := &configv1.HealthCheck{
Passive: &configv1.PassiveHealthCheck{
Type: "redis",
},
}
err := tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.passive.Type",
reason: "invalid value",
})
// invalid passive health check healthy successes
hc = &configv1.HealthCheck{
Passive: &configv1.PassiveHealthCheck{
Type: "http",
Healthy: &configv1.PassiveHealthCheckHealthy{
Successes: -1,
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.passive.healthy.successes",
reason: "invalid value",
})
// empty passive health check healthy httpCodes.
hc = &configv1.HealthCheck{
Passive: &configv1.PassiveHealthCheck{
Type: "http",
Healthy: &configv1.PassiveHealthCheckHealthy{
Successes: 1,
HTTPCodes: []int{},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.passive.healthy.httpCodes",
reason: "empty",
})
// empty passive health check unhealthy httpFailures.
hc = &configv1.HealthCheck{
Passive: &configv1.PassiveHealthCheck{
Type: "http",
Unhealthy: &configv1.PassiveHealthCheckUnhealthy{
HTTPFailures: -1,
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.passive.unhealthy.httpFailures",
reason: "invalid value",
})
// empty passive health check unhealthy tcpFailures.
hc = &configv1.HealthCheck{
Passive: &configv1.PassiveHealthCheck{
Type: "http",
Unhealthy: &configv1.PassiveHealthCheckUnhealthy{
TCPFailures: -1,
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.passive.unhealthy.tcpFailures",
reason: "invalid value",
})
// empty passive health check unhealthy httpCodes.
hc = &configv1.HealthCheck{
Passive: &configv1.PassiveHealthCheck{
Type: "http",
Unhealthy: &configv1.PassiveHealthCheckUnhealthy{
HTTPCodes: []int{},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.passive.unhealthy.httpCodes",
reason: "empty",
})
}
func TestTranslateUpstreamActiveHealthCheckUnusually(t *testing.T) {
tr := &translator{}
// invalid active health check type
hc := &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "redis",
},
}
err := tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.Type",
reason: "invalid value",
})
// invalid active health check port value
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "http",
Port: 65536,
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.port",
reason: "invalid value",
})
// invalid active health check concurrency value
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Concurrency: -1,
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.concurrency",
reason: "invalid value",
})
// invalid active health check healthy successes value
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Healthy: &configv1.ActiveHealthCheckHealthy{
PassiveHealthCheckHealthy: configv1.PassiveHealthCheckHealthy{
Successes: -1,
},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.healthy.successes",
reason: "invalid value",
})
// invalid active health check healthy successes value
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Healthy: &configv1.ActiveHealthCheckHealthy{
PassiveHealthCheckHealthy: configv1.PassiveHealthCheckHealthy{
HTTPCodes: []int{},
},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.healthy.httpCodes",
reason: "empty",
})
// invalid active health check healthy interval
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Healthy: &configv1.ActiveHealthCheckHealthy{
Interval: metav1.Duration{Duration: 500 * time.Millisecond},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.healthy.interval",
reason: "invalid value",
})
// missing active health check healthy interval
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Healthy: &configv1.ActiveHealthCheckHealthy{},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.healthy.interval",
reason: "invalid value",
})
// invalid active health check unhealthy httpFailures
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Unhealthy: &configv1.ActiveHealthCheckUnhealthy{
PassiveHealthCheckUnhealthy: configv1.PassiveHealthCheckUnhealthy{
HTTPFailures: -1,
},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.unhealthy.httpFailures",
reason: "invalid value",
})
// invalid active health check unhealthy tcpFailures
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Unhealthy: &configv1.ActiveHealthCheckUnhealthy{
PassiveHealthCheckUnhealthy: configv1.PassiveHealthCheckUnhealthy{
TCPFailures: -1,
},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.unhealthy.tcpFailures",
reason: "invalid value",
})
// invalid active health check unhealthy httpCodes
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Unhealthy: &configv1.ActiveHealthCheckUnhealthy{
PassiveHealthCheckUnhealthy: configv1.PassiveHealthCheckUnhealthy{
HTTPCodes: []int{},
},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.unhealthy.httpCodes",
reason: "empty",
})
// invalid active health check unhealthy interval
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Unhealthy: &configv1.ActiveHealthCheckUnhealthy{
Interval: metav1.Duration{Duration: 500 * time.Millisecond},
},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.unhealthy.interval",
reason: "invalid value",
})
// missing active health check unhealthy interval
hc = &configv1.HealthCheck{
Active: &configv1.ActiveHealthCheck{
Type: "https",
Unhealthy: &configv1.ActiveHealthCheckUnhealthy{},
},
}
err = tr.translateUpstreamHealthCheck(hc, nil)
assert.Equal(t, err, &translateError{
field: "healthCheck.active.unhealthy.interval",
reason: "invalid value",
})
}
func TestUpstreamRetriesAndTimeout(t *testing.T) {
tr := &translator{}
err := tr.translateUpstreamRetriesAndTimeout(-1, nil, nil)
assert.Equal(t, err, &translateError{
field: "retries",
reason: "invalid value",
})
var ups apisixv1.Upstream
err = tr.translateUpstreamRetriesAndTimeout(3, nil, &ups)
assert.Nil(t, err)
assert.Equal(t, ups.Retries, 3)
timeout := &configv1.UpstreamTimeout{
Connect: metav1.Duration{Duration: time.Second},
Read: metav1.Duration{Duration: -1},
}
err = tr.translateUpstreamRetriesAndTimeout(3, timeout, &ups)
assert.Equal(t, err, &translateError{
field: "timeout.read",
reason: "invalid value",
})
timeout = &configv1.UpstreamTimeout{
Connect: metav1.Duration{Duration: time.Second},
Read: metav1.Duration{Duration: 15 * time.Second},
}
err = tr.translateUpstreamRetriesAndTimeout(3, timeout, &ups)
assert.Nil(t, err)
assert.Equal(t, ups.Timeout, &apisixv1.UpstreamTimeout{
Connect: 1,
Send: 60,
Read: 15,
})
}