Skip to content
Merged
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
2 changes: 2 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion pkg/reconciler/autoscaling/hpa/hpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package hpa

import (
"context"
"errors"
"testing"

// Inject our fake informers
Expand All @@ -35,6 +36,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
corev1 "k8s.io/api/core/v1"
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ktesting "k8s.io/client-go/testing"
Expand All @@ -47,6 +49,7 @@ import (
asv1a1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1"
"knative.dev/serving/pkg/apis/networking"
nv1a1 "knative.dev/serving/pkg/apis/networking/v1alpha1"
"knative.dev/serving/pkg/apis/serving/v1alpha1"
"knative.dev/serving/pkg/autoscaler"
"knative.dev/serving/pkg/reconciler"
areconciler "knative.dev/serving/pkg/reconciler/autoscaling"
Expand Down Expand Up @@ -90,6 +93,7 @@ func TestControllerCanReconcile(t *testing.T) {
}

func TestReconcile(t *testing.T) {
retryAttempted := false
const (
deployName = testRevision + "-deployment"
privateSvc = testRevision + "-private"
Expand Down Expand Up @@ -123,12 +127,21 @@ func TestReconcile(t *testing.T) {
WithHPAClass, WithMetricAnnotation(autoscaling.Concurrency)), privateSvc),
}},
}, {
Name: "create hpa & sks",
Name: "create hpa & sks, with retry",
Objects: []runtime.Object{
pa(testNamespace, testRevision, WithHPAClass),
deploy(testNamespace, testRevision),
},
Key: key(testNamespace, testRevision),
WithReactors: []ktesting.ReactionFunc{
func(action ktesting.Action) (handled bool, ret runtime.Object, err error) {
if retryAttempted || !action.Matches("update", "podautoscalers") || action.GetSubresource() != "status" {
return false, nil, nil
}
retryAttempted = true
return true, nil, apierrs.NewConflict(v1alpha1.Resource("foo"), "bar", errors.New("foo"))
},
},
WantCreates: []runtime.Object{
sks(testNamespace, testRevision, WithDeployRef(deployName)),
hpa(pa(testNamespace, testRevision,
Expand All @@ -137,6 +150,9 @@ func TestReconcile(t *testing.T) {
WantStatusUpdates: []ktesting.UpdateActionImpl{{
Object: pa(testNamespace, testRevision, WithHPAClass, withScales(0, 0),
WithNoTraffic("ServicesNotReady", "SKS Services are not ready yet")),
}, {
Object: pa(testNamespace, testRevision, WithHPAClass, withScales(0, 0),
WithNoTraffic("ServicesNotReady", "SKS Services are not ready yet")),
}},
}, {
Name: "create metric when Concurrency used",
Expand Down Expand Up @@ -441,6 +457,7 @@ func TestReconcile(t *testing.T) {
}}

table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler {
retryAttempted = false
ctx = podscalable.WithDuck(ctx)

return &Reconciler{
Expand Down
16 changes: 15 additions & 1 deletion pkg/reconciler/autoscaling/kpa/kpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ func TestReconcile(t *testing.T) {
zeroEndpoints := makeSKSPrivateEndpoints(0, testNamespace, testRevision)

deciderKey := struct{}{}
retryAttempted := false

// Note: due to how KPA reconciler works we are dependent on the
// two constant objects above, which means, that all tests must share
Expand Down Expand Up @@ -286,7 +287,7 @@ func TestReconcile(t *testing.T) {
defaultDeployment, defaultEndpoints,
},
}, {
Name: "no endpoints",
Name: "no endpoints, with retry",
Key: key,
Objects: []runtime.Object{
kpa(testNamespace, testRevision, WithPAMetricsService(privateSvc), WithPAStatusService(testRevision),
Expand All @@ -295,9 +296,21 @@ func TestReconcile(t *testing.T) {
metric(testNamespace, testRevision),
defaultDeployment,
},
WithReactors: []clientgotesting.ReactionFunc{
func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
if retryAttempted || !action.Matches("update", "podautoscalers") || action.GetSubresource() != "status" {
return false, nil, nil
}
retryAttempted = true
return true, nil, apierrors.NewConflict(v1alpha1.Resource("foo"), "bar", errors.New("foo"))
},
},
WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
Object: kpa(testNamespace, testRevision, markUnknown, WithPAMetricsService(privateSvc), withScales(1, defaultScale),
WithPAStatusService(testRevision)),
}, {
Object: kpa(testNamespace, testRevision, markUnknown, WithPAMetricsService(privateSvc), withScales(1, defaultScale),
WithPAStatusService(testRevision)),
}},
WantErr: true,
WantEvents: []string{
Expand Down Expand Up @@ -955,6 +968,7 @@ func TestReconcile(t *testing.T) {
}}

table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler {
retryAttempted = false
ctx = podscalable.WithDuck(ctx)

fakeDeciders := newTestDeciders()
Expand Down
3 changes: 2 additions & 1 deletion pkg/reconciler/autoscaling/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"knative.dev/pkg/apis/duck"
"knative.dev/pkg/logging"
pkgreconciler "knative.dev/pkg/reconciler"
"knative.dev/serving/pkg/apis/autoscaling"
pav1alpha1 "knative.dev/serving/pkg/apis/autoscaling/v1alpha1"
"knative.dev/serving/pkg/apis/networking"
Expand Down Expand Up @@ -140,7 +141,7 @@ func (c *Base) ReconcileMetric(ctx context.Context, pa *pav1alpha1.PodAutoscaler
// UpdateStatus updates the status of the given PodAutoscaler.
func (c *Base) UpdateStatus(existing *pav1alpha1.PodAutoscaler, desired *pav1alpha1.PodAutoscaler) error {
existing = existing.DeepCopy()
return reconciler.RetryUpdateConflicts(func(attempts int) (err error) {
return pkgreconciler.RetryUpdateConflicts(func(attempts int) (err error) {
// The first iteration tries to use the informer's state, subsequent attempts fetch the latest state via API.
if attempts > 0 {
existing, err = c.ServingClientSet.AutoscalingV1alpha1().PodAutoscalers(desired.Namespace).Get(desired.Name, metav1.GetOptions{})
Expand Down
3 changes: 2 additions & 1 deletion pkg/reconciler/certificate/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"knative.dev/pkg/apis"
"knative.dev/pkg/controller"
"knative.dev/pkg/logging"
pkgreconciler "knative.dev/pkg/reconciler"
"knative.dev/pkg/tracker"
"knative.dev/serving/pkg/apis/networking/v1alpha1"
certmanagerclientset "knative.dev/serving/pkg/client/certmanager/clientset/versioned"
Expand Down Expand Up @@ -207,7 +208,7 @@ func (c *Reconciler) reconcileCMCertificate(ctx context.Context, knCert *v1alpha

func (c *Reconciler) updateStatus(existing *v1alpha1.Certificate, desired *v1alpha1.Certificate) error {
existing = existing.DeepCopy()
return reconciler.RetryUpdateConflicts(func(attempts int) (err error) {
return pkgreconciler.RetryUpdateConflicts(func(attempts int) (err error) {
Comment thread
nlopezgi marked this conversation as resolved.
// The first iteration tries to use the informer's state, subsequent attempts fetch the latest state via API.
if attempts > 0 {
existing, err = c.ServingClientSet.NetworkingV1alpha1().Certificates(desired.Namespace).Get(desired.Name, metav1.GetOptions{})
Expand Down
29 changes: 28 additions & 1 deletion pkg/reconciler/certificate/certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package certificate

import (
"context"
"errors"
"fmt"
"hash/adler32"
"testing"
Expand All @@ -34,6 +35,7 @@ import (
cmv1alpha2 "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
cmmeta "github.com/jetstack/cert-manager/pkg/apis/meta/v1"
corev1 "k8s.io/api/core/v1"
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgotesting "k8s.io/client-go/testing"
Expand Down Expand Up @@ -102,18 +104,28 @@ func TestNewController(t *testing.T) {

// This is heavily based on the way the OpenShift Ingress controller tests its reconciliation method.
func TestReconcile(t *testing.T) {
retryAttempted := false
table := TableTest{{
Name: "bad workqueue key",
Key: "too/many/parts",
}, {
Name: "key not found",
Key: "foo/not-found",
}, {
Name: "create CM certificate matching Knative Certificate",
Name: "create CM certificate matching Knative Certificate, with retry",
Objects: []runtime.Object{
knCert("knCert", "foo"),
nonHTTP01Issuer,
},
WithReactors: []clientgotesting.ReactionFunc{
func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
if retryAttempted || !action.Matches("update", "certificates") || action.GetSubresource() != "status" {
return false, nil, nil
}
retryAttempted = true
return true, nil, apierrs.NewConflict(v1alpha1.Resource("foo"), "bar", errors.New("foo"))
},
},
WantCreates: []runtime.Object{
resources.MakeCertManagerCertificate(certmanagerConfig(), knCert("knCert", "foo")),
},
Expand All @@ -131,6 +143,20 @@ func TestReconcile(t *testing.T) {
}},
},
}),
}, {
Object: knCertWithStatus("knCert", "foo",
&v1alpha1.CertificateStatus{
Status: duckv1.Status{
ObservedGeneration: generation,
Conditions: duckv1.Conditions{{
Type: v1alpha1.CertificateConditionReady,
Status: corev1.ConditionUnknown,
Severity: apis.ConditionSeverityError,
Reason: noCMConditionReason,
Message: noCMConditionMessage,
}},
},
}),
}},
WantEvents: []string{
Eventf(corev1.EventTypeNormal, "Created", "Created Cert-Manager Certificate %s/%s", "foo", "knCert"),
Expand Down Expand Up @@ -319,6 +345,7 @@ func TestReconcile(t *testing.T) {
}}

table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler {
retryAttempted = false
return &Reconciler{
Base: reconciler.NewBase(ctx, controllerAgentName, cmw),
knCertificateLister: listers.GetKnCertificateLister(),
Expand Down
3 changes: 2 additions & 1 deletion pkg/reconciler/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"k8s.io/client-go/tools/cache"
"knative.dev/pkg/controller"
"knative.dev/pkg/logging"
pkgreconciler "knative.dev/pkg/reconciler"
"knative.dev/serving/pkg/apis/serving"
v1 "knative.dev/serving/pkg/apis/serving/v1"
"knative.dev/serving/pkg/apis/serving/v1alpha1"
Expand Down Expand Up @@ -343,7 +344,7 @@ func (c *Reconciler) createRevision(ctx context.Context, config *v1alpha1.Config

func (c *Reconciler) updateStatus(existing *v1alpha1.Configuration, desired *v1alpha1.Configuration) error {
existing = existing.DeepCopy()
return reconciler.RetryUpdateConflicts(func(attempts int) (err error) {
return pkgreconciler.RetryUpdateConflicts(func(attempts int) (err error) {
// The first iteration tries to use the informer's state, subsequent attempts fetch the latest state via API.
if attempts > 0 {
existing, err = c.ServingClientSet.ServingV1alpha1().Configurations(desired.Namespace).Get(desired.Name, metav1.GetOptions{})
Expand Down
20 changes: 19 additions & 1 deletion pkg/reconciler/configuration/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package configuration

import (
"context"
"errors"
"testing"
"time"

Expand All @@ -26,6 +27,7 @@ import (
_ "knative.dev/serving/pkg/client/injection/informers/serving/v1alpha1/revision/fake"

corev1 "k8s.io/api/core/v1"
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgotesting "k8s.io/client-go/testing"
Expand Down Expand Up @@ -56,6 +58,7 @@ var revisionSpec = v1alpha1.RevisionSpec{

// This is heavily based on the way the OpenShift Ingress controller tests its reconciliation method.
func TestReconcile(t *testing.T) {
retryAttempted := false
now := time.Now()

table := TableTest{{
Expand All @@ -72,10 +75,19 @@ func TestReconcile(t *testing.T) {
},
Key: "foo/delete-pending",
}, {
Name: "create revision matching generation",
Name: "create revision matching generation, with retry",
Objects: []runtime.Object{
cfg("no-revisions-yet", "foo", 1234),
},
WithReactors: []clientgotesting.ReactionFunc{
func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
if retryAttempted || !action.Matches("update", "configurations") || action.GetSubresource() != "status" {
return false, nil, nil
}
retryAttempted = true
return true, nil, apierrs.NewConflict(v1alpha1.Resource("foo"), "bar", errors.New("foo"))
},
},
WantCreates: []runtime.Object{
rev("no-revisions-yet", "foo", 1234),
},
Expand All @@ -84,6 +96,11 @@ func TestReconcile(t *testing.T) {
// The following properties are set when we first reconcile a
// Configuration and a Revision is created.
WithLatestCreated("no-revisions-yet-00001"), WithObservedGen),
}, {
Object: cfg("no-revisions-yet", "foo", 1234,
// The following properties are set when we first reconcile a
// Configuration and a Revision is created.
WithLatestCreated("no-revisions-yet-00001"), WithObservedGen),
}},
WantEvents: []string{
Eventf(corev1.EventTypeNormal, "Created", "Created Revision %q", "no-revisions-yet-00001"),
Expand Down Expand Up @@ -455,6 +472,7 @@ func TestReconcile(t *testing.T) {
}}

table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler {
retryAttempted = false
return &Reconciler{
Base: reconciler.NewBase(ctx, controllerAgentName, cmw),
configurationLister: listers.GetConfigurationLister(),
Expand Down
3 changes: 2 additions & 1 deletion pkg/reconciler/ingress/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
listers "knative.dev/serving/pkg/client/listers/networking/v1alpha1"

"knative.dev/pkg/controller"
pkgreconciler "knative.dev/pkg/reconciler"
"knative.dev/pkg/tracker"
istiolisters "knative.dev/serving/pkg/client/istio/listers/networking/v1alpha3"

Expand Down Expand Up @@ -329,7 +330,7 @@ func (r *Reconciler) reconcileDeletion(ctx context.Context, ing *v1alpha1.Ingres
// for semantic differences before calling.
func (r *Reconciler) updateStatus(existing *v1alpha1.Ingress, desired *v1alpha1.Ingress) error {
existing = existing.DeepCopy()
return reconciler.RetryUpdateConflicts(func(attempts int) (err error) {
return pkgreconciler.RetryUpdateConflicts(func(attempts int) (err error) {
// The first iteration tries to use the informer's state, subsequent attempts fetch the latest state via API.
if attempts > 0 {
existing, err = r.ServingClientSet.NetworkingV1alpha1().Ingresses(desired.GetNamespace()).Get(desired.GetName(), metav1.GetOptions{})
Expand Down
Loading