[GLBC] Support backside re-encryption (#519)
Support backside re-encryption
This commit is contained in:
parent
7f3763590a
commit
642cb74cc7
21 changed files with 1046 additions and 433 deletions
|
|
@ -17,86 +17,98 @@ limitations under the License.
|
|||
package healthchecks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/ingress/controllers/gce/utils"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
// NewFakeHealthChecks returns a new FakeHealthChecks.
|
||||
func NewFakeHealthChecks() *FakeHealthChecks {
|
||||
return &FakeHealthChecks{hc: []*compute.HttpHealthCheck{}}
|
||||
func fakeNotFoundErr() *googleapi.Error {
|
||||
return &googleapi.Error{Code: 404}
|
||||
}
|
||||
|
||||
// FakeHealthCheckGetter implements the healthCheckGetter interface for tests.
|
||||
type FakeHealthCheckGetter struct {
|
||||
DefaultHealthCheck *compute.HttpHealthCheck
|
||||
}
|
||||
|
||||
// HealthCheck returns the health check for the given port. If a health check
|
||||
// isn't stored under the DefaultHealthCheck member, it constructs one.
|
||||
func (h *FakeHealthCheckGetter) HealthCheck(port int64) (*compute.HttpHealthCheck, error) {
|
||||
if h.DefaultHealthCheck == nil {
|
||||
return utils.DefaultHealthCheckTemplate(port), nil
|
||||
// NewFakeHealthCheckProvider returns a new FakeHealthChecks.
|
||||
func NewFakeHealthCheckProvider() *FakeHealthCheckProvider {
|
||||
return &FakeHealthCheckProvider{
|
||||
http: make(map[string]compute.HttpHealthCheck),
|
||||
generic: make(map[string]compute.HealthCheck),
|
||||
}
|
||||
return h.DefaultHealthCheck, nil
|
||||
}
|
||||
|
||||
// FakeHealthChecks fakes out health checks.
|
||||
type FakeHealthChecks struct {
|
||||
hc []*compute.HttpHealthCheck
|
||||
// FakeHealthCheckProvider fakes out health checks.
|
||||
type FakeHealthCheckProvider struct {
|
||||
http map[string]compute.HttpHealthCheck
|
||||
generic map[string]compute.HealthCheck
|
||||
}
|
||||
|
||||
// CreateHttpHealthCheck fakes out http health check creation.
|
||||
func (f *FakeHealthChecks) CreateHttpHealthCheck(hc *compute.HttpHealthCheck) error {
|
||||
f.hc = append(f.hc, hc)
|
||||
func (f *FakeHealthCheckProvider) CreateHttpHealthCheck(hc *compute.HttpHealthCheck) error {
|
||||
v := *hc
|
||||
v.SelfLink = "https://fake.google.com/compute/httpHealthChecks/" + hc.Name
|
||||
f.http[hc.Name] = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHttpHealthCheck fakes out getting a http health check from the cloud.
|
||||
func (f *FakeHealthChecks) GetHttpHealthCheck(name string) (*compute.HttpHealthCheck, error) {
|
||||
for _, h := range f.hc {
|
||||
if h.Name == name {
|
||||
return h, nil
|
||||
}
|
||||
func (f *FakeHealthCheckProvider) GetHttpHealthCheck(name string) (*compute.HttpHealthCheck, error) {
|
||||
if hc, found := f.http[name]; found {
|
||||
return &hc, nil
|
||||
}
|
||||
return nil, fmt.Errorf("health check %v not found", name)
|
||||
|
||||
return nil, fakeNotFoundErr()
|
||||
}
|
||||
|
||||
// DeleteHttpHealthCheck fakes out deleting a http health check.
|
||||
func (f *FakeHealthChecks) DeleteHttpHealthCheck(name string) error {
|
||||
healthChecks := []*compute.HttpHealthCheck{}
|
||||
exists := false
|
||||
for _, h := range f.hc {
|
||||
if h.Name == name {
|
||||
exists = true
|
||||
continue
|
||||
}
|
||||
healthChecks = append(healthChecks, h)
|
||||
func (f *FakeHealthCheckProvider) DeleteHttpHealthCheck(name string) error {
|
||||
if _, exists := f.http[name]; !exists {
|
||||
return fakeNotFoundErr()
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("failed to find health check %v", name)
|
||||
}
|
||||
f.hc = healthChecks
|
||||
|
||||
delete(f.http, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateHttpHealthCheck sends the given health check as an update.
|
||||
func (f *FakeHealthChecks) UpdateHttpHealthCheck(hc *compute.HttpHealthCheck) error {
|
||||
healthChecks := []*compute.HttpHealthCheck{}
|
||||
found := false
|
||||
for _, h := range f.hc {
|
||||
if h.Name == hc.Name {
|
||||
healthChecks = append(healthChecks, hc)
|
||||
found = true
|
||||
} else {
|
||||
healthChecks = append(healthChecks, h)
|
||||
}
|
||||
func (f *FakeHealthCheckProvider) UpdateHttpHealthCheck(hc *compute.HttpHealthCheck) error {
|
||||
if _, exists := f.http[hc.Name]; !exists {
|
||||
return fakeNotFoundErr()
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("cannot update a non-existent health check %v", hc.Name)
|
||||
}
|
||||
f.hc = healthChecks
|
||||
|
||||
f.http[hc.Name] = *hc
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateHealthCheck fakes out http health check creation.
|
||||
func (f *FakeHealthCheckProvider) CreateHealthCheck(hc *compute.HealthCheck) error {
|
||||
v := *hc
|
||||
v.SelfLink = "https://fake.google.com/compute/healthChecks/" + hc.Name
|
||||
f.generic[hc.Name] = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHealthCheck fakes out getting a http health check from the cloud.
|
||||
func (f *FakeHealthCheckProvider) GetHealthCheck(name string) (*compute.HealthCheck, error) {
|
||||
if hc, found := f.generic[name]; found {
|
||||
return &hc, nil
|
||||
}
|
||||
|
||||
return nil, fakeNotFoundErr()
|
||||
}
|
||||
|
||||
// DeleteHealthCheck fakes out deleting a http health check.
|
||||
func (f *FakeHealthCheckProvider) DeleteHealthCheck(name string) error {
|
||||
if _, exists := f.generic[name]; !exists {
|
||||
return fakeNotFoundErr()
|
||||
}
|
||||
|
||||
delete(f.generic, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateHealthCheck sends the given health check as an update.
|
||||
func (f *FakeHealthCheckProvider) UpdateHealthCheck(hc *compute.HealthCheck) error {
|
||||
if _, exists := f.generic[hc.Name]; !exists {
|
||||
return fakeNotFoundErr()
|
||||
}
|
||||
|
||||
f.generic[hc.Name] = *hc
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,77 +18,200 @@ package healthchecks
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"github.com/golang/glog"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/ingress/controllers/gce/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
// These values set a low health threshold and a high failure threshold.
|
||||
// We're just trying to detect if the node networking is
|
||||
// borked, service level outages will get detected sooner
|
||||
// by kube-proxy.
|
||||
// DefaultHealthCheckInterval defines how frequently a probe runs
|
||||
DefaultHealthCheckInterval = 60 * time.Second
|
||||
// DefaultHealthyThreshold defines the threshold of success probes that declare a backend "healthy"
|
||||
DefaultHealthyThreshold = 1
|
||||
// DefaultUnhealthyThreshold defines the threshold of failure probes that declare a backend "unhealthy"
|
||||
DefaultUnhealthyThreshold = 10
|
||||
// DefaultTimeout defines the timeout of each probe
|
||||
DefaultTimeout = 60 * time.Second
|
||||
)
|
||||
|
||||
// HealthChecks manages health checks.
|
||||
type HealthChecks struct {
|
||||
cloud SingleHealthCheck
|
||||
cloud HealthCheckProvider
|
||||
defaultPath string
|
||||
namer *utils.Namer
|
||||
healthCheckGetter
|
||||
}
|
||||
|
||||
// NewHealthChecker creates a new health checker.
|
||||
// cloud: the cloud object implementing SingleHealthCheck.
|
||||
// defaultHealthCheckPath: is the HTTP path to use for health checks.
|
||||
func NewHealthChecker(cloud SingleHealthCheck, defaultHealthCheckPath string, namer *utils.Namer) HealthChecker {
|
||||
return &HealthChecks{cloud, defaultHealthCheckPath, namer, nil}
|
||||
func NewHealthChecker(cloud HealthCheckProvider, defaultHealthCheckPath string, namer *utils.Namer) HealthChecker {
|
||||
return &HealthChecks{cloud, defaultHealthCheckPath, namer}
|
||||
}
|
||||
|
||||
// Init initializes the health checker.
|
||||
func (h *HealthChecks) Init(r healthCheckGetter) {
|
||||
h.healthCheckGetter = r
|
||||
// New returns a *HealthCheck with default settings and specified port/protocol
|
||||
func (h *HealthChecks) New(port int64, protocol utils.AppProtocol) *HealthCheck {
|
||||
hc := DefaultHealthCheck(port, protocol)
|
||||
hc.Name = h.namer.BeName(port)
|
||||
return hc
|
||||
}
|
||||
|
||||
// Add adds a healthcheck if one for the same port doesn't already exist.
|
||||
func (h *HealthChecks) Add(port int64) error {
|
||||
wantHC, err := h.healthCheckGetter.HealthCheck(port)
|
||||
// Sync retrieves a health check based on port, checks type and settings and updates/creates if necessary.
|
||||
// Sync is only called by the backends.Add func - it's not a pool like other resources.
|
||||
func (h *HealthChecks) Sync(hc *HealthCheck) (string, error) {
|
||||
// Verify default path
|
||||
if hc.RequestPath == "" {
|
||||
hc.RequestPath = h.defaultPath
|
||||
}
|
||||
|
||||
existingHC, err := h.Get(hc.Port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if wantHC.RequestPath == "" {
|
||||
wantHC.RequestPath = h.defaultPath
|
||||
}
|
||||
name := h.namer.BeName(port)
|
||||
wantHC.Name = name
|
||||
hc, _ := h.Get(port)
|
||||
if hc == nil {
|
||||
// TODO: check if the readiness probe has changed and update the
|
||||
// health check.
|
||||
glog.Infof("Creating health check %v", name)
|
||||
if err := h.cloud.CreateHttpHealthCheck(wantHC); err != nil {
|
||||
return err
|
||||
if !utils.IsHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return "", err
|
||||
}
|
||||
} else if wantHC.RequestPath != hc.RequestPath {
|
||||
|
||||
glog.V(2).Infof("Creating health check for port %v with protocol %v", hc.Port, hc.Type)
|
||||
if err = h.cloud.CreateHealthCheck(hc.ToComputeHealthCheck()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return h.getHealthCheckLink(hc.Port)
|
||||
}
|
||||
|
||||
if existingHC.Protocol() != hc.Protocol() {
|
||||
glog.V(2).Infof("Updating health check %v because it has protocol %v but need %v", existingHC.Name, existingHC.Type, hc.Type)
|
||||
err = h.cloud.UpdateHealthCheck(hc.ToComputeHealthCheck())
|
||||
return existingHC.SelfLink, err
|
||||
}
|
||||
|
||||
if existingHC.RequestPath != hc.RequestPath {
|
||||
// TODO: reconcile health checks, and compare headers interval etc.
|
||||
// Currently Ingress doesn't expose all the health check params
|
||||
// natively, so some users prefer to hand modify the check.
|
||||
glog.Infof("Unexpected request path on health check %v, has %v want %v, NOT reconciling",
|
||||
name, hc.RequestPath, wantHC.RequestPath)
|
||||
glog.V(2).Infof("Unexpected request path on health check %v, has %v want %v, NOT reconciling", hc.Name, existingHC.RequestPath, hc.RequestPath)
|
||||
} else {
|
||||
glog.Infof("Health check %v already exists and has the expected path %v", hc.Name, hc.RequestPath)
|
||||
glog.V(2).Infof("Health check %v already exists and has the expected path %v", hc.Name, hc.RequestPath)
|
||||
}
|
||||
return nil
|
||||
|
||||
return existingHC.SelfLink, nil
|
||||
}
|
||||
|
||||
func (h *HealthChecks) getHealthCheckLink(port int64) (string, error) {
|
||||
hc, err := h.Get(port)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hc.SelfLink, nil
|
||||
}
|
||||
|
||||
// Delete deletes the health check by port.
|
||||
func (h *HealthChecks) Delete(port int64) error {
|
||||
name := h.namer.BeName(port)
|
||||
glog.Infof("Deleting health check %v", name)
|
||||
if err := h.cloud.DeleteHttpHealthCheck(h.namer.BeName(port)); err != nil {
|
||||
if !utils.IsHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
glog.V(2).Infof("Deleting health check %v", name)
|
||||
return h.cloud.DeleteHealthCheck(name)
|
||||
}
|
||||
|
||||
// Get returns the given health check.
|
||||
func (h *HealthChecks) Get(port int64) (*compute.HttpHealthCheck, error) {
|
||||
return h.cloud.GetHttpHealthCheck(h.namer.BeName(port))
|
||||
// Get returns the health check by port
|
||||
func (h *HealthChecks) Get(port int64) (*HealthCheck, error) {
|
||||
name := h.namer.BeName(port)
|
||||
hc, err := h.cloud.GetHealthCheck(name)
|
||||
return NewHealthCheck(hc), err
|
||||
}
|
||||
|
||||
// DeleteLegacy deletes legacy HTTP health checks
|
||||
func (h *HealthChecks) DeleteLegacy(port int64) error {
|
||||
name := h.namer.BeName(port)
|
||||
glog.V(2).Infof("Deleting legacy HTTP health check %v", name)
|
||||
return h.cloud.DeleteHttpHealthCheck(name)
|
||||
}
|
||||
|
||||
// DefaultHealthCheck simply returns the default health check.
|
||||
func DefaultHealthCheck(port int64, protocol utils.AppProtocol) *HealthCheck {
|
||||
httpSettings := compute.HTTPHealthCheck{
|
||||
Port: port,
|
||||
// Empty string is used as a signal to the caller to use the appropriate
|
||||
// default.
|
||||
RequestPath: "",
|
||||
}
|
||||
|
||||
hcSettings := compute.HealthCheck{
|
||||
// How often to health check.
|
||||
CheckIntervalSec: int64(DefaultHealthCheckInterval.Seconds()),
|
||||
// How long to wait before claiming failure of a health check.
|
||||
TimeoutSec: int64(DefaultTimeout.Seconds()),
|
||||
// Number of healthchecks to pass for a vm to be deemed healthy.
|
||||
HealthyThreshold: DefaultHealthyThreshold,
|
||||
// Number of healthchecks to fail before the vm is deemed unhealthy.
|
||||
UnhealthyThreshold: DefaultUnhealthyThreshold,
|
||||
Description: "Default kubernetes L7 Loadbalancing health check.",
|
||||
Type: string(protocol),
|
||||
}
|
||||
|
||||
return &HealthCheck{
|
||||
HTTPHealthCheck: httpSettings,
|
||||
HealthCheck: hcSettings,
|
||||
}
|
||||
}
|
||||
|
||||
// HealthCheck embeds two types - the generic healthcheck compute.HealthCheck
|
||||
// and the HTTP settings compute.HTTPHealthCheck. By embedding both, consumers can modify
|
||||
// all relevant settings (HTTP specific and HealthCheck generic) regardless of Type
|
||||
// Consumers should call .Out() func to generate a compute.HealthCheck
|
||||
// with the proper child struct (.HttpHealthCheck, .HttpshealthCheck, etc).
|
||||
type HealthCheck struct {
|
||||
compute.HTTPHealthCheck
|
||||
compute.HealthCheck
|
||||
}
|
||||
|
||||
// NewHealthCheck creates a HealthCheck which abstracts nested structs away
|
||||
func NewHealthCheck(hc *compute.HealthCheck) *HealthCheck {
|
||||
if hc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := &HealthCheck{HealthCheck: *hc}
|
||||
switch utils.AppProtocol(hc.Type) {
|
||||
case utils.ProtocolHTTP:
|
||||
v.HTTPHealthCheck = *hc.HttpHealthCheck
|
||||
case utils.ProtocolHTTPS:
|
||||
// HTTPHealthCheck and HTTPSHealthChecks have identical fields
|
||||
v.HTTPHealthCheck = compute.HTTPHealthCheck(*hc.HttpsHealthCheck)
|
||||
}
|
||||
|
||||
// Users should be modifying HTTP(S) specific settings on the embedded
|
||||
// HTTPHealthCheck. Setting these to nil for preventing confusion.
|
||||
v.HealthCheck.HttpHealthCheck = nil
|
||||
v.HealthCheck.HttpsHealthCheck = nil
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Protocol returns the type cased to AppProtocol
|
||||
func (hc *HealthCheck) Protocol() utils.AppProtocol {
|
||||
return utils.AppProtocol(hc.Type)
|
||||
}
|
||||
|
||||
// ToComputeHealthCheck returns a valid compute.HealthCheck object
|
||||
func (hc *HealthCheck) ToComputeHealthCheck() *compute.HealthCheck {
|
||||
// Zeroing out child settings as a precaution. GoogleAPI throws an error
|
||||
// if the wrong child struct is set.
|
||||
hc.HealthCheck.HttpsHealthCheck = nil
|
||||
hc.HealthCheck.HttpHealthCheck = nil
|
||||
|
||||
switch hc.Protocol() {
|
||||
case utils.ProtocolHTTP:
|
||||
hc.HealthCheck.HttpHealthCheck = &hc.HTTPHealthCheck
|
||||
case utils.ProtocolHTTPS:
|
||||
https := compute.HTTPSHealthCheck(hc.HTTPHealthCheck)
|
||||
hc.HealthCheck.HttpsHealthCheck = &https
|
||||
}
|
||||
|
||||
return &hc.HealthCheck
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,47 +17,170 @@ limitations under the License.
|
|||
package healthchecks
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/ingress/controllers/gce/utils"
|
||||
)
|
||||
|
||||
func TestFakeHealthCheckActions(t *testing.T) {
|
||||
namer := &utils.Namer{}
|
||||
healthChecks := NewHealthChecker(NewFakeHealthChecks(), "/", namer)
|
||||
healthChecks.Init(&FakeHealthCheckGetter{DefaultHealthCheck: nil})
|
||||
func TestHealthCheckAdd(t *testing.T) {
|
||||
namer := utils.NewNamer("ABC", "XYZ")
|
||||
hcp := NewFakeHealthCheckProvider()
|
||||
healthChecks := NewHealthChecker(hcp, "/", namer)
|
||||
|
||||
err := healthChecks.Add(80)
|
||||
hc := healthChecks.New(80, utils.ProtocolHTTP)
|
||||
_, err := healthChecks.Sync(hc)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error")
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
_, err1 := healthChecks.Get(8080)
|
||||
if err1 == nil {
|
||||
t.Errorf("expected error")
|
||||
}
|
||||
|
||||
hc, err2 := healthChecks.Get(80)
|
||||
if err2 != nil {
|
||||
t.Errorf("unexpected error")
|
||||
} else {
|
||||
if hc == nil {
|
||||
t.Errorf("expected a *compute.HttpHealthCheck")
|
||||
}
|
||||
}
|
||||
|
||||
err = healthChecks.Delete(8080)
|
||||
if err == nil {
|
||||
t.Errorf("expected error")
|
||||
}
|
||||
|
||||
err = healthChecks.Delete(80)
|
||||
// Verify the health check exists
|
||||
_, err = hcp.GetHealthCheck(namer.BeName(80))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error")
|
||||
t.Fatalf("expected the health check to exist, err: %v", err)
|
||||
}
|
||||
|
||||
_, err3 := healthChecks.Get(80)
|
||||
if err3 == nil {
|
||||
t.Errorf("expected error")
|
||||
hc = healthChecks.New(443, utils.ProtocolHTTPS)
|
||||
_, err = healthChecks.Sync(hc)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
// Verify the health check exists
|
||||
_, err = hcp.GetHealthCheck(namer.BeName(443))
|
||||
if err != nil {
|
||||
t.Fatalf("expected the health check to exist, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheckAddExisting(t *testing.T) {
|
||||
namer := &utils.Namer{}
|
||||
hcp := NewFakeHealthCheckProvider()
|
||||
healthChecks := NewHealthChecker(hcp, "/", namer)
|
||||
|
||||
// HTTP
|
||||
// Manually insert a health check
|
||||
httpHC := DefaultHealthCheck(3000, utils.ProtocolHTTP)
|
||||
httpHC.Name = namer.BeName(3000)
|
||||
httpHC.RequestPath = "/my-probes-health"
|
||||
hcp.CreateHealthCheck(httpHC.ToComputeHealthCheck())
|
||||
|
||||
// Should not fail adding the same type of health check
|
||||
hc := healthChecks.New(3000, utils.ProtocolHTTP)
|
||||
_, err := healthChecks.Sync(hc)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
// Verify the health check exists
|
||||
_, err = hcp.GetHealthCheck(httpHC.Name)
|
||||
if err != nil {
|
||||
t.Fatalf("expected the health check to continue existing, err: %v", err)
|
||||
}
|
||||
|
||||
// HTTPS
|
||||
// Manually insert a health check
|
||||
httpsHC := DefaultHealthCheck(4000, utils.ProtocolHTTPS)
|
||||
httpsHC.Name = namer.BeName(4000)
|
||||
httpsHC.RequestPath = "/my-probes-health"
|
||||
hcp.CreateHealthCheck(httpsHC.ToComputeHealthCheck())
|
||||
|
||||
hc = healthChecks.New(4000, utils.ProtocolHTTPS)
|
||||
_, err = healthChecks.Sync(hc)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
// Verify the health check exists
|
||||
_, err = hcp.GetHealthCheck(httpsHC.Name)
|
||||
if err != nil {
|
||||
t.Fatalf("expected the health check to continue existing, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheckDelete(t *testing.T) {
|
||||
namer := &utils.Namer{}
|
||||
hcp := NewFakeHealthCheckProvider()
|
||||
healthChecks := NewHealthChecker(hcp, "/", namer)
|
||||
|
||||
// Create HTTP HC for 1234
|
||||
hc := DefaultHealthCheck(1234, utils.ProtocolHTTP)
|
||||
hc.Name = namer.BeName(1234)
|
||||
hcp.CreateHealthCheck(hc.ToComputeHealthCheck())
|
||||
|
||||
// Create HTTPS HC for 1234)
|
||||
hc.Type = string(utils.ProtocolHTTPS)
|
||||
hcp.CreateHealthCheck(hc.ToComputeHealthCheck())
|
||||
|
||||
// Delete only HTTP 1234
|
||||
err := healthChecks.Delete(1234)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error when deleting health check, err: %v", err)
|
||||
}
|
||||
|
||||
// Validate port is deleted
|
||||
_, err = hcp.GetHealthCheck(hc.Name)
|
||||
if !utils.IsHTTPErrorCode(err, http.StatusNotFound) {
|
||||
t.Errorf("expected not-found error, actual: %v", err)
|
||||
}
|
||||
|
||||
// Delete only HTTP 1234
|
||||
err = healthChecks.Delete(1234)
|
||||
if err == nil {
|
||||
t.Errorf("expected not-found error when deleting health check, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheckUpdate(t *testing.T) {
|
||||
namer := &utils.Namer{}
|
||||
hcp := NewFakeHealthCheckProvider()
|
||||
healthChecks := NewHealthChecker(hcp, "/", namer)
|
||||
|
||||
// HTTP
|
||||
// Manually insert a health check
|
||||
hc := DefaultHealthCheck(3000, utils.ProtocolHTTP)
|
||||
hc.Name = namer.BeName(3000)
|
||||
hc.RequestPath = "/my-probes-health"
|
||||
hcp.CreateHealthCheck(hc.ToComputeHealthCheck())
|
||||
|
||||
// Verify the health check exists
|
||||
_, err := healthChecks.Get(3000)
|
||||
if err != nil {
|
||||
t.Fatalf("expected the health check to exist, err: %v", err)
|
||||
}
|
||||
|
||||
// Change to HTTPS
|
||||
hc.Type = string(utils.ProtocolHTTPS)
|
||||
_, err = healthChecks.Sync(hc)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err while syncing healthcheck, err %v", err)
|
||||
}
|
||||
|
||||
// Verify the health check exists
|
||||
_, err = healthChecks.Get(3000)
|
||||
if err != nil {
|
||||
t.Fatalf("expected the health check to exist, err: %v", err)
|
||||
}
|
||||
|
||||
// Verify the check is now HTTPS
|
||||
if hc.Protocol() != utils.ProtocolHTTPS {
|
||||
t.Fatalf("expected check to be of type HTTPS")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHealthCheckDeleteLegacy(t *testing.T) {
|
||||
namer := &utils.Namer{}
|
||||
hcp := NewFakeHealthCheckProvider()
|
||||
healthChecks := NewHealthChecker(hcp, "/", namer)
|
||||
|
||||
err := hcp.CreateHttpHealthCheck(&compute.HttpHealthCheck{
|
||||
Name: namer.BeName(80),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("expected health check to be created, err: %v", err)
|
||||
}
|
||||
|
||||
err = healthChecks.DeleteLegacy(80)
|
||||
if err != nil {
|
||||
t.Fatalf("expected health check to be deleted, err: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,27 +18,28 @@ package healthchecks
|
|||
|
||||
import (
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/ingress/controllers/gce/utils"
|
||||
)
|
||||
|
||||
// healthCheckGetter retrieves health checks.
|
||||
type healthCheckGetter interface {
|
||||
// HealthCheck returns the HTTP readiness check for a node port.
|
||||
HealthCheck(nodePort int64) (*compute.HttpHealthCheck, error)
|
||||
}
|
||||
|
||||
// SingleHealthCheck is an interface to manage a single GCE health check.
|
||||
type SingleHealthCheck interface {
|
||||
// HealthCheckProvider is an interface to manage a single GCE health check.
|
||||
type HealthCheckProvider interface {
|
||||
CreateHttpHealthCheck(hc *compute.HttpHealthCheck) error
|
||||
UpdateHttpHealthCheck(hc *compute.HttpHealthCheck) error
|
||||
DeleteHttpHealthCheck(name string) error
|
||||
GetHttpHealthCheck(name string) (*compute.HttpHealthCheck, error)
|
||||
|
||||
CreateHealthCheck(hc *compute.HealthCheck) error
|
||||
UpdateHealthCheck(hc *compute.HealthCheck) error
|
||||
DeleteHealthCheck(name string) error
|
||||
GetHealthCheck(name string) (*compute.HealthCheck, error)
|
||||
}
|
||||
|
||||
// HealthChecker is an interface to manage cloud HTTPHealthChecks.
|
||||
type HealthChecker interface {
|
||||
Init(h healthCheckGetter)
|
||||
|
||||
Add(port int64) error
|
||||
New(port int64, protocol utils.AppProtocol) *HealthCheck
|
||||
Sync(hc *HealthCheck) (string, error)
|
||||
Delete(port int64) error
|
||||
Get(port int64) (*compute.HttpHealthCheck, error)
|
||||
Get(port int64) (*HealthCheck, error)
|
||||
DeleteLegacy(port int64) error
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue