ACME HTTP01 solver: clean up ingresses if the service name changes

Signed-off-by: Oliver Powell <oliver@opowell.com>
This commit is contained in:
Oliver Powell 2019-12-13 15:42:42 +02:00
parent b365021dc8
commit 7611f78793
2 changed files with 63 additions and 1 deletions

View File

@ -87,10 +87,18 @@ func (s *Solver) ensureIngress(ctx context.Context, ch *cmacme.Challenge, svcNam
if err != nil {
return nil, err
}
if len(existingIngresses) == 1 {
if len(existingIngresses) == 1 && ingressServiceName(existingIngresses[0]) == svcName {
logf.WithRelatedResource(log, existingIngresses[0]).Info("found one existing HTTP01 solver ingress")
return existingIngresses[0], nil
}
if len(existingIngresses) == 1 && ingressServiceName(existingIngresses[0]) != svcName {
log.Info("service name changed. cleaning up all existing ingresses.")
err := s.cleanupIngresses(ctx, ch)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("service name changed, existing challenge solver ingresses found and cleaned up. retrying challenge sync")
}
if len(existingIngresses) > 1 {
log.Info("multiple challenge solver ingresses found for challenge. cleaning up all existing ingresses.")
err := s.cleanupIngresses(ctx, ch)
@ -104,6 +112,10 @@ func (s *Solver) ensureIngress(ctx context.Context, ch *cmacme.Challenge, svcNam
return s.createIngress(ch, svcName)
}
func ingressServiceName(ing *extv1beta1.Ingress) string {
return ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServiceName
}
// createIngress will create a challenge solving pod for the given certificate,
// domain, token and key.
func (s *Solver) createIngress(ch *cmacme.Challenge, svcName string) (*extv1beta1.Ingress, error) {

View File

@ -25,6 +25,7 @@ import (
"k8s.io/api/extensions/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/intstr"
@ -378,3 +379,52 @@ func TestCleanupIngresses(t *testing.T) {
})
}
}
func TestEnsureIngress(t *testing.T) {
tests := map[string]solverFixture{
"should clean up if service name changes": {
Challenge: &cmacme.Challenge{
Spec: cmacme.ChallengeSpec{
DNSName: "example.com",
Solver: &cmacme.ACMEChallengeSolver{
HTTP01: &cmacme.ACMEChallengeSolverHTTP01{
Ingress: &cmacme.ACMEChallengeSolverHTTP01Ingress{},
},
},
},
},
Err: true,
PreFn: func(t *testing.T, s *solverFixture) {
_, err := s.Solver.createIngress(s.Challenge, "anotherfakeservice")
if err != nil {
t.Errorf("error preparing test: %v", err)
}
s.Builder.Sync()
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
ingresses, err := s.Solver.ingressLister.List(labels.NewSelector())
if err != nil {
t.Errorf("error listing ingresses: %v", err)
t.Fail()
return
}
if len(ingresses) != 0 {
t.Errorf("expected ingresses to have been cleaned up, but there were %d ingresses left", len(ingresses))
}
},
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
test.Setup(t)
resp, err := test.Solver.ensureIngress(context.TODO(), test.Challenge, "fakeservice")
if err != nil && !test.Err {
t.Errorf("Expected function to not error, but got: %v", err)
}
if err == nil && test.Err {
t.Errorf("Expected function to get an error, but got: %v", err)
}
test.Finish(t, resp, err)
})
}
}