Skip to content

Commit

Permalink
e2e tests for dynamic configuration and Lua features and a bug fix (#…
Browse files Browse the repository at this point in the history
…2254)

* e2e tests for dynamic configuration and Lua features

* do not rely on force reload to dynamically configure when reload is needed

* fix misspelling

* skip dynamic configuration in the first template rendering

* dont error on first sync
  • Loading branch information
ElvinEfendi authored and aledbf committed Apr 1, 2018
1 parent e761191 commit ee46f48
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 31 deletions.
46 changes: 23 additions & 23 deletions internal/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,41 +169,41 @@ func (n *NGINXController) syncIngress(item interface{}) error {
if !n.isForceReload() && n.runningConfig.Equal(&pcfg) {
glog.V(3).Infof("skipping backend reload (no changes detected)")
return nil
} else if !n.isForceReload() && n.cfg.DynamicConfigurationEnabled && n.IsDynamicallyConfigurable(&pcfg) {
err := n.ConfigureDynamically(&pcfg)
if err == nil {
glog.Infof("dynamic reconfiguration succeeded, skipping reload")
n.runningConfig = &pcfg
return nil
}

glog.Warningf("falling back to reload, could not dynamically reconfigure: %v", err)
}

glog.Infof("backend reload required")
if n.cfg.DynamicConfigurationEnabled && n.IsDynamicConfigurationEnough(&pcfg) && !n.isForceReload() {
glog.Infof("skipping reload")
} else {
glog.Infof("backend reload required")

err := n.OnUpdate(pcfg)
if err != nil {
incReloadErrorCount()
glog.Errorf("unexpected failure restarting the backend: \n%v", err)
return err
err := n.OnUpdate(pcfg)
if err != nil {
incReloadErrorCount()
glog.Errorf("unexpected failure restarting the backend: \n%v", err)
return err
}

glog.Infof("ingress backend successfully reloaded...")
incReloadCount()
setSSLExpireTime(servers)
}

glog.Infof("ingress backend successfully reloaded...")
incReloadCount()
setSSLExpireTime(servers)
if n.cfg.DynamicConfigurationEnabled {
isFirstSync := n.runningConfig.Equal(&ingress.Configuration{})
go func(isFirstSync bool) {
if isFirstSync {
glog.Infof("first sync of Nginx configuration")

if n.isForceReload() && n.cfg.DynamicConfigurationEnabled {
go func() {
// it takes time for Nginx to start listening on the port
time.Sleep(1 * time.Second)
// it takes time for Nginx to start listening on the port
time.Sleep(1 * time.Second)
}
err := n.ConfigureDynamically(&pcfg)
if err == nil {
glog.Infof("dynamic reconfiguration succeeded")
} else {
glog.Warningf("could not dynamically reconfigure: %v", err)
}
}()
}(isFirstSync)
}

n.runningConfig = &pcfg
Expand Down
4 changes: 2 additions & 2 deletions internal/ingress/controller/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,8 +751,8 @@ func (n *NGINXController) setupSSLProxy() {
}()
}

// IsDynamicallyConfigurable decides if the new configuration can be dynamically configured without reloading
func (n *NGINXController) IsDynamicallyConfigurable(pcfg *ingress.Configuration) bool {
// IsDynamicConfigurationEnough decides if the new configuration changes can be dynamically applied without reloading
func (n *NGINXController) IsDynamicConfigurationEnough(pcfg *ingress.Configuration) bool {
var copyOfRunningConfig ingress.Configuration = *n.runningConfig
var copyOfPcfg ingress.Configuration = *pcfg

Expand Down
8 changes: 4 additions & 4 deletions internal/ingress/controller/nginx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"k8s.io/ingress-nginx/internal/ingress"
)

func TestIsDynamicallyConfigurable(t *testing.T) {
func TestIsDynamicConfigurationEnough(t *testing.T) {
backends := []*ingress.Backend{{
Name: "fakenamespace-myapp-80",
Endpoints: []ingress.Endpoint{
Expand Down Expand Up @@ -60,23 +60,23 @@ func TestIsDynamicallyConfigurable(t *testing.T) {
}

newConfig := commonConfig
if !n.IsDynamicallyConfigurable(newConfig) {
if !n.IsDynamicConfigurationEnough(newConfig) {
t.Errorf("When new config is same as the running config it should be deemed as dynamically configurable")
}

newConfig = &ingress.Configuration{
Backends: []*ingress.Backend{{Name: "another-backend-8081"}},
Servers: []*ingress.Server{{Hostname: "myapp1.fake"}},
}
if n.IsDynamicallyConfigurable(newConfig) {
if n.IsDynamicConfigurationEnough(newConfig) {
t.Errorf("Expected to not be dynamically configurable when there's more than just backends change")
}

newConfig = &ingress.Configuration{
Backends: []*ingress.Backend{{Name: "a-backend-8080"}},
Servers: servers,
}
if !n.IsDynamicallyConfigurable(newConfig) {
if !n.IsDynamicConfigurationEnough(newConfig) {
t.Errorf("Expected to be dynamically configurable when only backends change")
}

Expand Down
1 change: 1 addition & 0 deletions test/e2e/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
// tests to run
_ "k8s.io/ingress-nginx/test/e2e/annotations"
_ "k8s.io/ingress-nginx/test/e2e/defaultbackend"
_ "k8s.io/ingress-nginx/test/e2e/lua"
_ "k8s.io/ingress-nginx/test/e2e/settings"
_ "k8s.io/ingress-nginx/test/e2e/ssl"
)
Expand Down
24 changes: 24 additions & 0 deletions test/e2e/framework/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ import (
"strings"
"time"

appsv1beta1 "k8s.io/api/apps/v1beta1"
"k8s.io/api/core/v1"
apiextcs "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest"

"github.com/golang/glog"
"github.com/pkg/errors"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -255,3 +258,24 @@ func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) b
return false, nil
}
}

// UpdateDeployment runs the given updateFunc on the deployment and waits for it to be updated
func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name string, replicas int, updateFunc func(d *appsv1beta1.Deployment) error) error {
deployment, err := kubeClientSet.AppsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return err
}

if err = updateFunc(deployment); err != nil {
return err
}

err = WaitForPodsReady(kubeClientSet, 60*time.Second, replicas, namespace, metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(deployment.Spec.Template.ObjectMeta.Labels)).String(),
})
if err != nil {
return errors.Wrap(err, "failed to wait for nginx-ingress-controller pods to restart")
}

return nil
}
10 changes: 8 additions & 2 deletions test/e2e/framework/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
)

// EnsureSecret creates a Secret object or returns it if it already exists.
Expand Down Expand Up @@ -75,10 +76,15 @@ func (f *Framework) EnsureDeployment(deployment *extensions.Deployment) (*extens
return d, nil
}

// WaitForPodsReady waits for a given amount of time until a group of Pods is running.
// WaitForPodsReady waits for a given amount of time until a group of Pods is running in the framework's namespace.
func (f *Framework) WaitForPodsReady(timeout time.Duration, expectedReplicas int, opts metav1.ListOptions) error {
return WaitForPodsReady(f.KubeClientSet, timeout, expectedReplicas, f.Namespace.Name, opts)
}

// WaitForPodsReady waits for a given amount of time until a group of Pods is running in the given namespace.
func WaitForPodsReady(kubeClientSet kubernetes.Interface, timeout time.Duration, expectedReplicas int, namespace string, opts metav1.ListOptions) error {
return wait.Poll(time.Second, timeout, func() (bool, error) {
pl, err := f.KubeClientSet.CoreV1().Pods(f.Namespace.Name).List(opts)
pl, err := kubeClientSet.CoreV1().Pods(namespace).List(opts)
if err != nil {
return false, err
}
Expand Down
Loading

0 comments on commit ee46f48

Please sign in to comment.