Align autoscaling annotations in tests (#1531)

* Align autoscaling annotations in unit tests

* Fix code style

* Fix e2e tests
This commit is contained in:
David Simansky 2021-11-26 14:34:51 +01:00 committed by GitHub
parent 0e89cfccbe
commit 2b1e77de20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 324 additions and 191 deletions

8
go.mod
View File

@ -18,10 +18,10 @@ require (
k8s.io/cli-runtime v0.21.4 k8s.io/cli-runtime v0.21.4
k8s.io/client-go v0.21.4 k8s.io/client-go v0.21.4
k8s.io/code-generator v0.21.4 k8s.io/code-generator v0.21.4
knative.dev/eventing v0.27.1-0.20211123070249-2cda8f40b5d9 knative.dev/eventing v0.27.1-0.20211123205351-820db20be4b2
knative.dev/hack v0.0.0-20211122162614-813559cefdda knative.dev/hack v0.0.0-20211122162614-813559cefdda
knative.dev/networking v0.0.0-20211123024050-aa82452902be knative.dev/networking v0.0.0-20211124064027-ea794f17c1bf
knative.dev/pkg v0.0.0-20211123074649-0fae0afc10ad knative.dev/pkg v0.0.0-20211123135150-787aec59e70a
knative.dev/serving v0.27.1-0.20211123120750-26c7dc6ccc53 knative.dev/serving v0.27.1-0.20211124064027-e6f8e414ac9e
sigs.k8s.io/yaml v1.3.0 sigs.k8s.io/yaml v1.3.0
) )

19
go.sum
View File

@ -1735,25 +1735,24 @@ k8s.io/legacy-cloud-providers v0.21.0/go.mod h1:bNxo7gDg+PGkBmT/MFZswLTWdSWK9kAl
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ= k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ=
k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
knative.dev/caching v0.0.0-20211122134815-4f6b1e562337/go.mod h1:awOzz1AtzphZ5YbuMa3ZfRTN2IqRcLaiknYYuCZPZOA= knative.dev/caching v0.0.0-20211123074749-2c27e22a9971/go.mod h1:/5cq0Jmn8O7zOptuBNUh/iHgy3yS7ZJ1hyEf/8Eof08=
knative.dev/eventing v0.27.1-0.20211123070249-2cda8f40b5d9 h1:8GhioMgKtYTPbcEjzBsMd2g+KfUMiMurqnuD1EU9KNE= knative.dev/eventing v0.27.1-0.20211123205351-820db20be4b2 h1:QwyD6phsrqx5hDplMkFZ6NJPLMSnxN3YjAw+Qnnrbpg=
knative.dev/eventing v0.27.1-0.20211123070249-2cda8f40b5d9/go.mod h1:fnBpTKtPOxC7WOaQY6WUiUAVBXTb44njuhTi7LXHGVc= knative.dev/eventing v0.27.1-0.20211123205351-820db20be4b2/go.mod h1:fnBpTKtPOxC7WOaQY6WUiUAVBXTb44njuhTi7LXHGVc=
knative.dev/hack v0.0.0-20211101195839-11d193bf617b/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack v0.0.0-20211101195839-11d193bf617b/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
knative.dev/hack v0.0.0-20211112192837-128cf0150a69/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack v0.0.0-20211112192837-128cf0150a69/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
knative.dev/hack v0.0.0-20211117134436-69a2295d54ce/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
knative.dev/hack v0.0.0-20211122162614-813559cefdda h1:WBfGcmu5pN+RCxDotKVYtWlJVI2V4Hvah+XD9mcSR/o= knative.dev/hack v0.0.0-20211122162614-813559cefdda h1:WBfGcmu5pN+RCxDotKVYtWlJVI2V4Hvah+XD9mcSR/o=
knative.dev/hack v0.0.0-20211122162614-813559cefdda/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= knative.dev/hack v0.0.0-20211122162614-813559cefdda/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
knative.dev/hack/schema v0.0.0-20211122162614-813559cefdda/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0= knative.dev/hack/schema v0.0.0-20211122162614-813559cefdda/go.mod h1:ffjwmdcrH5vN3mPhO8RrF2KfNnbHeCE2C60A+2cv3U0=
knative.dev/networking v0.0.0-20211122065314-75d86c5d4128/go.mod h1:UCDjE4GxZJat8RJohbAwwxe+U3LjRJOU2Hb2LNiNMY0=
knative.dev/networking v0.0.0-20211123024050-aa82452902be h1:E9JdH2VCkl+pfCGExsTtwW158HrSCuCCoOfYHGn+mf0=
knative.dev/networking v0.0.0-20211123024050-aa82452902be/go.mod h1:u/Biwu9curBfc1GvZE293SwEfLo84sZ6df7cymgwLvw= knative.dev/networking v0.0.0-20211123024050-aa82452902be/go.mod h1:u/Biwu9curBfc1GvZE293SwEfLo84sZ6df7cymgwLvw=
knative.dev/networking v0.0.0-20211124064027-ea794f17c1bf h1:qoRaPCrq3ymaBxK7XV0JOm0Pu+sAgFlTNYQh+pBwS8k=
knative.dev/networking v0.0.0-20211124064027-ea794f17c1bf/go.mod h1:ZYtIxKNhCdg8lle16ADEyy/C0ANH9rhJokx5C9dzjDE=
knative.dev/pkg v0.0.0-20211101212339-96c0204a70dc/go.mod h1:SkfDk9bWIiNZD7XtILGkG7AKVyF/M6M0bGxLgl0SYL8= knative.dev/pkg v0.0.0-20211101212339-96c0204a70dc/go.mod h1:SkfDk9bWIiNZD7XtILGkG7AKVyF/M6M0bGxLgl0SYL8=
knative.dev/pkg v0.0.0-20211120133512-d016976f2567/go.mod h1:VqUp1KWJqpTDNoiSI/heaX3uMdubImslJE2tBkP+Bbw= knative.dev/pkg v0.0.0-20211120133512-d016976f2567/go.mod h1:VqUp1KWJqpTDNoiSI/heaX3uMdubImslJE2tBkP+Bbw=
knative.dev/pkg v0.0.0-20211123074649-0fae0afc10ad h1:d5EVnV0T5JX403WUx2scfr1tE/MY9xIY92qJoxCcm1I= knative.dev/pkg v0.0.0-20211123135150-787aec59e70a h1:mgE9GdkjfPJc7KpgBox52dSy1GsQmsFTWXy+1HjEn9I=
knative.dev/pkg v0.0.0-20211123074649-0fae0afc10ad/go.mod h1:fZUlVceKtVNyFU6LokWGk2a9QFQXeSTtnbKOjjkQ690= knative.dev/pkg v0.0.0-20211123135150-787aec59e70a/go.mod h1:fZUlVceKtVNyFU6LokWGk2a9QFQXeSTtnbKOjjkQ690=
knative.dev/reconciler-test v0.0.0-20211112132636-ae9e2e21972f/go.mod h1:gTsbLk496j/M9xqMpx/liyCQ0X3bwDpRtcs2Zzws364= knative.dev/reconciler-test v0.0.0-20211112132636-ae9e2e21972f/go.mod h1:gTsbLk496j/M9xqMpx/liyCQ0X3bwDpRtcs2Zzws364=
knative.dev/serving v0.27.1-0.20211123120750-26c7dc6ccc53 h1:Sw0cdAMaOpGZ9iY2kzmoOBv9oe/mUh1ubdW+U6S7b2M= knative.dev/serving v0.27.1-0.20211124064027-e6f8e414ac9e h1:/Mhn3Z9tM2T+uT/D9sSCtT7QNzwUtofmW24vGUuc9wA=
knative.dev/serving v0.27.1-0.20211123120750-26c7dc6ccc53/go.mod h1:lVEraTokiW04QvfhBaZh4BPn9DAeqL4Gs9yaRbVV4ks= knative.dev/serving v0.27.1-0.20211124064027-e6f8e414ac9e/go.mod h1:VgFSdL4RDG+HAnRod0mtlhwrYJnVAkfuR5m/sH03/c8=
pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

View File

@ -507,9 +507,9 @@ func TestServiceCreateWithBothAnnotationAndInitScaleAsOption(t *testing.T) {
r := client.Recorder() r := client.Recorder()
output, err := executeServiceCommand(client, "create", "foo", "--image", "gcr.io/foo/bar:baz", "--annotation", "autoscaling.knative.dev/initialScale=0", "--scale-init", "0") output, err := executeServiceCommand(client, "create", "foo", "--image", "gcr.io/foo/bar:baz", "--annotation", autoscaling.InitialScaleAnnotationKey+"=0", "--scale-init", "0")
assert.Assert(t, err != nil) assert.Assert(t, err != nil)
assert.Assert(t, util.ContainsAll(output, "only one of the", "--scale-init", "--annotation", "autoscaling.knative.dev/initialScale", "can be specified")) assert.Assert(t, util.ContainsAll(output, "only one of the", "--scale-init", "--annotation", autoscaling.InitialScaleAnnotationKey, "can be specified"))
r.Validate() r.Validate()
} }
@ -641,7 +641,7 @@ func TestServiceCreateWithScaleServiceAnnotationsError(t *testing.T) {
"--annotation-service", autoscaling.InitialScaleAnnotationKey+"=1", "--annotation-service", autoscaling.InitialScaleAnnotationKey+"=1",
"--no-wait") "--no-wait")
assert.Assert(t, err != nil) assert.Assert(t, err != nil)
assert.Assert(t, util.ContainsAll(output, "service can not have auto-scaling related annotation", "autoscaling.knative.dev/initialScale")) assert.Assert(t, util.ContainsAll(output, "service can not have auto-scaling related annotation", autoscaling.InitialScaleAnnotationKey))
r.Validate() r.Validate()
} }

View File

@ -24,6 +24,8 @@ import (
"strings" "strings"
"testing" "testing"
"knative.dev/serving/pkg/apis/autoscaling"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
api_errors "k8s.io/apimachinery/pkg/api/errors" api_errors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -406,11 +408,11 @@ func TestServiceCreateMaxMinScale(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1", autoscaling.MinScaleAnnotationKey, "1",
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
"autoscaling.knative.dev/target", "10", autoscaling.TargetAnnotationKey, "10",
"autoscaling.knative.dev/targetUtilizationPercentage", "50", autoscaling.TargetUtilizationPercentageKey, "50",
"autoscaling.knative.dev/window", "10s", autoscaling.WindowAnnotationKey, "10s",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -441,8 +443,8 @@ func TestServiceCreateScale(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "5", autoscaling.MinScaleAnnotationKey, "5",
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -461,7 +463,7 @@ func TestServiceCreateScaleWithNegativeValue(t *testing.T) {
if err == nil { if err == nil {
t.Fatal(err) t.Fatal(err)
} }
expectedErrMsg := "expected 0 <= -1 <= 2147483647: autoscaling.knative.dev/maxScale" expectedErrMsg := "expected 0 <= -1 <= 2147483647: " + autoscaling.MaxScaleAnnotationKey
if !strings.Contains(err.Error(), expectedErrMsg) { if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err) t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err)
} }
@ -522,8 +524,8 @@ func TestServiceCreateScaleRange(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1", autoscaling.MinScaleAnnotationKey, "1",
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -551,7 +553,7 @@ func TestServiceCreateScaleRangeOnlyMin(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1", autoscaling.MinScaleAnnotationKey, "1",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -570,7 +572,7 @@ func TestServiceCreateScaleRangeOnlyMinNegative(t *testing.T) {
if err == nil { if err == nil {
t.Fatal(err) t.Fatal(err)
} }
expectedErrMsg := "expected 0 <= -1 <= 2147483647: autoscaling.knative.dev/minScale" expectedErrMsg := "expected 0 <= -1 <= 2147483647: " + autoscaling.MinScaleAnnotationKey
if !strings.Contains(err.Error(), expectedErrMsg) { if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err) t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err)
} }
@ -592,7 +594,7 @@ func TestServiceCreateScaleRangeOnlyMax(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -611,7 +613,7 @@ func TestServiceCreateScaleRangeOnlyMaxNegative(t *testing.T) {
if err == nil { if err == nil {
t.Fatal(err) t.Fatal(err)
} }
expectedErrMsg := "expected 0 <= -5 <= 2147483647: autoscaling.knative.dev/maxScale" expectedErrMsg := "expected 0 <= -5 <= 2147483647: " + autoscaling.MaxScaleAnnotationKey
if !strings.Contains(err.Error(), expectedErrMsg) { if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err) t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err)
} }
@ -1080,5 +1082,5 @@ func TestServiceCreateFromYAMLWithOverrideError(t *testing.T) {
_, _, _, err = fakeServiceCreate([]string{ _, _, _, err = fakeServiceCreate([]string{
"service", "create", "foo", "--filename", tempFile, "--scale", "-1"}, false) "service", "create", "foo", "--filename", tempFile, "--scale", "-1"}, false)
assert.Assert(t, err != nil) assert.Assert(t, err != nil)
assert.Assert(t, util.ContainsAll(err.Error(), "expected", "0", "<=", "2147483647", "autoscaling.knative.dev/maxScale")) assert.Assert(t, util.ContainsAll(err.Error(), "expected", "0", "<=", "2147483647", autoscaling.MaxScaleAnnotationKey))
} }

View File

@ -1500,7 +1500,7 @@ func TestServiceUpdateInitialScaleMock(t *testing.T) {
template := &newService.Spec.Template template := &newService.Spec.Template
template.Spec.Containers[0].Image = "gcr.io/foo/bar:baz" template.Spec.Containers[0].Image = "gcr.io/foo/bar:baz"
template.ObjectMeta.Annotations = map[string]string{ template.ObjectMeta.Annotations = map[string]string{
"autoscaling.knative.dev/initialScale": "1", autoscaling.InitialScaleAnnotationKey: "1",
clientserving.UserImageAnnotationKey: "gcr.io/foo/bar:baz", clientserving.UserImageAnnotationKey: "gcr.io/foo/bar:baz",
} }
@ -1508,7 +1508,7 @@ func TestServiceUpdateInitialScaleMock(t *testing.T) {
template = &updatedService.Spec.Template template = &updatedService.Spec.Template
template.Spec.Containers[0].Image = "gcr.io/foo/bar:baz" template.Spec.Containers[0].Image = "gcr.io/foo/bar:baz"
template.ObjectMeta.Annotations = map[string]string{ template.ObjectMeta.Annotations = map[string]string{
"autoscaling.knative.dev/initialScale": "2", autoscaling.InitialScaleAnnotationKey: "2",
clientserving.UserImageAnnotationKey: "gcr.io/foo/bar:baz", clientserving.UserImageAnnotationKey: "gcr.io/foo/bar:baz",
} }

View File

@ -23,6 +23,8 @@ import (
"testing" "testing"
"time" "time"
"knative.dev/serving/pkg/apis/autoscaling"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
"gotest.tools/v3/assert/cmp" "gotest.tools/v3/assert/cmp"
@ -387,10 +389,10 @@ func TestServiceUpdateMaxMinScale(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1", autoscaling.MinScaleAnnotationKey, "1",
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
"autoscaling.knative.dev/target", "10", autoscaling.TargetAnnotationKey, "10",
"autoscaling.knative.dev/targetUtilizationPercentage", "50", autoscaling.TargetUtilizationPercentageKey, "50",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -424,8 +426,8 @@ func TestServiceUpdateScale(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "5", autoscaling.MinScaleAnnotationKey, "5",
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -449,7 +451,7 @@ func TestServiceUpdateScaleWithNegativeValue(t *testing.T) {
t.Fatal("Expected error, got nil") t.Fatal("Expected error, got nil")
} }
expectedErrMsg := "expected 0 <= -1 <= 2147483647: autoscaling.knative.dev/maxScale" expectedErrMsg := "expected 0 <= -1 <= 2147483647: " + autoscaling.MaxScaleAnnotationKey
if !strings.Contains(err.Error(), expectedErrMsg) { if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err) t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err)
@ -512,8 +514,8 @@ func TestServiceUpdateScaleWithRange(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1", autoscaling.MinScaleAnnotationKey, "1",
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -543,7 +545,7 @@ func TestServiceUpdateScaleMinWithRange(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1", autoscaling.MinScaleAnnotationKey, "1",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -567,7 +569,7 @@ func TestServiceUpdateScaleMinWithRangeNegative(t *testing.T) {
t.Fatal("Expected error, got nil") t.Fatal("Expected error, got nil")
} }
expectedErrMsg := "expected 0 <= -1 <= 2147483647: autoscaling.knative.dev/minScale" expectedErrMsg := "expected 0 <= -1 <= 2147483647: " + autoscaling.MinScaleAnnotationKey
if !strings.Contains(err.Error(), expectedErrMsg) { if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err) t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err)
@ -592,7 +594,7 @@ func TestServiceUpdateScaleMaxWithRange(t *testing.T) {
actualAnnos := template.Annotations actualAnnos := template.Annotations
expectedAnnos := []string{ expectedAnnos := []string{
"autoscaling.knative.dev/maxScale", "5", autoscaling.MaxScaleAnnotationKey, "5",
} }
for i := 0; i < len(expectedAnnos); i += 2 { for i := 0; i < len(expectedAnnos); i += 2 {
@ -616,7 +618,7 @@ func TestServiceUpdateScaleMaxWithRangeNegative(t *testing.T) {
t.Fatal("Expected error, got nil") t.Fatal("Expected error, got nil")
} }
expectedErrMsg := "expected 0 <= -5 <= 2147483647: autoscaling.knative.dev/maxScale" expectedErrMsg := "expected 0 <= -5 <= 2147483647: " + autoscaling.MaxScaleAnnotationKey
if !strings.Contains(err.Error(), expectedErrMsg) { if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err) t.Errorf("Invalid error output, expected: %s, got : '%s'", expectedErrMsg, err)

View File

@ -155,7 +155,7 @@ func TestUpdateMinScale(t *testing.T) {
checkAnnotationValueInt(t, template, autoscaling.MinScaleAnnotationKey, 10) checkAnnotationValueInt(t, template, autoscaling.MinScaleAnnotationKey, 10)
// Update with invalid value // Update with invalid value
err = UpdateMinScale(template, -1) err = UpdateMinScale(template, -1)
assert.ErrorContains(t, err, "minScale") assert.ErrorContains(t, err, "min-scale")
} }
func TestUpdateMaxScale(t *testing.T) { func TestUpdateMaxScale(t *testing.T) {
@ -166,7 +166,7 @@ func TestUpdateMaxScale(t *testing.T) {
checkAnnotationValueInt(t, template, autoscaling.MaxScaleAnnotationKey, 10) checkAnnotationValueInt(t, template, autoscaling.MaxScaleAnnotationKey, 10)
// Update with invalid value // Update with invalid value
err = UpdateMaxScale(template, -1) err = UpdateMaxScale(template, -1)
assert.ErrorContains(t, err, "maxScale") assert.ErrorContains(t, err, "max-scale")
} }
func TestScaleWindow(t *testing.T) { func TestScaleWindow(t *testing.T) {

View File

@ -268,7 +268,7 @@ func validateServiceConcurrencyTarget(r *test.KnRunResultCollector, serviceName,
} }
func validateServiceConcurrencyUtilization(r *test.KnRunResultCollector, serviceName, concurrencyUtilization string) { func validateServiceConcurrencyUtilization(r *test.KnRunResultCollector, serviceName, concurrencyUtilization string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/targetUtilizationPercentage}" jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/target-utilization-percentage}"
out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath) out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(r.T(), out.Stdout, concurrencyUtilization) assert.Equal(r.T(), out.Stdout, concurrencyUtilization)
r.AssertNoError(out) r.AssertNoError(out)
@ -282,21 +282,21 @@ func validateScaleWindow(r *test.KnRunResultCollector, serviceName, window strin
} }
func validateServiceMinScale(r *test.KnRunResultCollector, serviceName, minScale string) { func validateServiceMinScale(r *test.KnRunResultCollector, serviceName, minScale string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/minScale}" jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/min-scale}"
out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath) out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(r.T(), out.Stdout, minScale) assert.Equal(r.T(), out.Stdout, minScale)
r.AssertNoError(out) r.AssertNoError(out)
} }
func validateServiceMaxScale(r *test.KnRunResultCollector, serviceName, maxScale string) { func validateServiceMaxScale(r *test.KnRunResultCollector, serviceName, maxScale string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/maxScale}" jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/max-scale}"
out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath) out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(r.T(), out.Stdout, maxScale) assert.Equal(r.T(), out.Stdout, maxScale)
r.AssertNoError(out) r.AssertNoError(out)
} }
func validateServiceInitScale(r *test.KnRunResultCollector, serviceName, initScale string) { func validateServiceInitScale(r *test.KnRunResultCollector, serviceName, initScale string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/initialScale}" jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/initial-scale}"
out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath) out := r.KnTest().Kn().Run("service", "list", serviceName, "-o", jsonpath)
assert.Equal(r.T(), out.Stdout, initScale) assert.Equal(r.T(), out.Stdout, initScale)
r.AssertNoError(out) r.AssertNoError(out)

View File

@ -20,9 +20,10 @@ import (
"context" "context"
"github.com/rickb777/date/period" "github.com/rickb777/date/period"
"knative.dev/eventing/pkg/apis/feature"
"knative.dev/pkg/apis" "knative.dev/pkg/apis"
duckv1 "knative.dev/pkg/apis/duck/v1" duckv1 "knative.dev/pkg/apis/duck/v1"
"knative.dev/eventing/pkg/apis/feature"
) )
// DeliverySpec contains the delivery options for event senders, // DeliverySpec contains the delivery options for event senders,
@ -60,6 +61,26 @@ type DeliverySpec struct {
// For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>. // For exponential policy, backoff delay is backoffDelay*2^<numberOfRetries>.
// +optional // +optional
BackoffDelay *string `json:"backoffDelay,omitempty"` BackoffDelay *string `json:"backoffDelay,omitempty"`
// RetryAfterMax provides an optional upper bound on the duration specified in a "Retry-After" header
// when calculating backoff times for retrying 429 and 503 response codes. Setting the value to
// zero ("PT0S") can be used to opt-out of respecting "Retry-After" header values altogether. This
// value only takes effect if "Retry" is configured, and also depends on specific implementations
// (Channels, Sources, etc.) choosing to provide this capability.
//
// Note: This API is EXPERIMENTAL and might be changed at anytime. While this experimental
// feature is in the Alpha/Beta stage, you must provide a valid value to opt-in for
// supporting "Retry-After" headers. When the feature becomes Stable/GA "Retry-After"
// headers will be respected by default, and you can choose to specify "PT0S" to
// opt-out of supporting "Retry-After" headers.
// For more details: https://github.com/knative/eventing/issues/5811
//
// More information on Duration format:
// - https://www.iso.org/iso-8601-date-and-time-format.html
// - https://en.wikipedia.org/wiki/ISO_8601
//
// +optional
RetryAfterMax *string `json:"retryAfterMax,omitempty"`
} }
func (ds *DeliverySpec) Validate(ctx context.Context) *apis.FieldError { func (ds *DeliverySpec) Validate(ctx context.Context) *apis.FieldError {
@ -101,6 +122,18 @@ func (ds *DeliverySpec) Validate(ctx context.Context) *apis.FieldError {
errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffDelay, "backoffDelay")) errs = errs.Also(apis.ErrInvalidValue(*ds.BackoffDelay, "backoffDelay"))
} }
} }
if ds.RetryAfterMax != nil {
if feature.FromContext(ctx).IsEnabled(feature.DeliveryRetryAfter) {
p, me := period.Parse(*ds.RetryAfterMax)
if me != nil || p.IsNegative() {
errs = errs.Also(apis.ErrInvalidValue(*ds.RetryAfterMax, "retryAfterMax"))
}
} else {
errs = errs.Also(apis.ErrDisallowedFields("retryAfterMax"))
}
}
return errs return errs
} }

View File

@ -163,6 +163,11 @@ func (in *DeliverySpec) DeepCopyInto(out *DeliverySpec) {
*out = new(string) *out = new(string)
**out = **in **out = **in
} }
if in.RetryAfterMax != nil {
in, out := &in.RetryAfterMax, &out.RetryAfterMax
*out = new(string)
**out = **in
}
return return
} }

View File

@ -18,6 +18,7 @@ package feature
const ( const (
KReferenceGroup = "kreference-group" KReferenceGroup = "kreference-group"
DeliveryRetryAfter = "delivery-retryafter"
DeliveryTimeout = "delivery-timeout" DeliveryTimeout = "delivery-timeout"
KReferenceMapping = "kreference-mapping" KReferenceMapping = "kreference-mapping"
StrictSubscriber = "strict-subscriber" StrictSubscriber = "strict-subscriber"

View File

@ -84,10 +84,6 @@ type metricsConfig struct {
// If duration is less than or equal to zero, it enables the default behavior. // If duration is less than or equal to zero, it enables the default behavior.
reportingPeriod time.Duration reportingPeriod time.Duration
// recorder provides a hook for performing custom transformations before
// writing the metrics to the stats.RecordWithOptions interface.
recorder func(context.Context, []stats.Measurement, ...stats.Options) error
// secret contains credentials for an exporter to use for authentication. // secret contains credentials for an exporter to use for authentication.
secret *corev1.Secret secret *corev1.Secret
@ -117,7 +113,6 @@ func (mc *metricsConfig) record(ctx context.Context, mss []stats.Measurement, ro
return nil return nil
} }
if mc.recorder == nil {
opt, err := optionForResource(metricskey.GetResource(ctx)) opt, err := optionForResource(metricskey.GetResource(ctx))
if err != nil { if err != nil {
return err return err
@ -126,8 +121,6 @@ func (mc *metricsConfig) record(ctx context.Context, mss []stats.Measurement, ro
return stats.RecordWithOptions(ctx, append(ros, stats.WithMeasurements(mss...))...) return stats.RecordWithOptions(ctx, append(ros, stats.WithMeasurements(mss...))...)
} }
return mc.recorder(ctx, mss, ros...)
}
func createMetricsConfig(_ context.Context, ops ExporterOptions) (*metricsConfig, error) { func createMetricsConfig(_ context.Context, ops ExporterOptions) (*metricsConfig, error) {
var mc metricsConfig var mc metricsConfig

View File

@ -26,11 +26,12 @@ import (
"time" "time"
"knative.dev/pkg/apis" "knative.dev/pkg/apis"
"knative.dev/pkg/kmap"
"knative.dev/serving/pkg/autoscaler/config/autoscalerconfig" "knative.dev/serving/pkg/autoscaler/config/autoscalerconfig"
) )
func getIntGE0(m map[string]string, k string) (int32, *apis.FieldError) { func getIntGE0(m map[string]string, key kmap.KeyPriority) (int32, *apis.FieldError) {
v, ok := m[k] k, v, ok := key.Get(m)
if !ok { if !ok {
return 0, nil return 0, nil
} }
@ -62,107 +63,109 @@ func ValidateAnnotations(ctx context.Context, config *autoscalerconfig.Config, a
Also(validateInitialScale(config, anns)) Also(validateInitialScale(config, anns))
} }
func validateClass(annotations map[string]string) *apis.FieldError { func validateClass(m map[string]string) *apis.FieldError {
if c, ok := annotations[ClassAnnotationKey]; ok { if k, v, ok := ClassAnnotation.Get(m); ok {
if strings.HasSuffix(c, domain) && c != KPA && c != HPA { if strings.HasSuffix(v, domain) && v != KPA && v != HPA {
return apis.ErrInvalidValue(c, ClassAnnotationKey) return apis.ErrInvalidValue(v, k)
} }
} }
return nil return nil
} }
func validateAlgorithm(annotations map[string]string) *apis.FieldError { func validateAlgorithm(m map[string]string) *apis.FieldError {
// Not a KPA? Don't validate, custom autoscalers might have custom values. // Not a KPA? Don't validate, custom autoscalers might have custom values.
if c := annotations[ClassAnnotationKey]; c != KPA { if _, v, _ := ClassAnnotation.Get(m); v != KPA {
return nil return nil
} }
if a := annotations[MetricAggregationAlgorithmKey]; a != "" { if k, v, _ := MetricAggregationAlgorithmAnnotation.Get(m); v != "" {
switch a { switch v {
case MetricAggregationAlgorithmLinear, MetricAggregationAlgorithmWeightedExponential: case MetricAggregationAlgorithmLinear,
MetricAggregationAlgorithmWeightedExponential,
MetricAggregationAlgorithmWeightedExponentialAlt:
return nil return nil
default: default:
return apis.ErrInvalidValue(a, MetricAggregationAlgorithmKey) return apis.ErrInvalidValue(v, k)
} }
} }
return nil return nil
} }
func validateFloats(annotations map[string]string) (errs *apis.FieldError) { func validateFloats(m map[string]string) (errs *apis.FieldError) {
if v, ok := annotations[PanicWindowPercentageAnnotationKey]; ok { if k, v, ok := PanicWindowPercentageAnnotation.Get(m); ok {
if fv, err := strconv.ParseFloat(v, 64); err != nil { if fv, err := strconv.ParseFloat(v, 64); err != nil {
errs = errs.Also(apis.ErrInvalidValue(v, PanicWindowPercentageAnnotationKey)) errs = errs.Also(apis.ErrInvalidValue(v, k))
} else if fv < PanicWindowPercentageMin || fv > PanicWindowPercentageMax { } else if fv < PanicWindowPercentageMin || fv > PanicWindowPercentageMax {
errs = apis.ErrOutOfBoundsValue(v, PanicWindowPercentageMin, errs = apis.ErrOutOfBoundsValue(v, PanicWindowPercentageMin,
PanicWindowPercentageMax, PanicWindowPercentageAnnotationKey) PanicWindowPercentageMax, k)
} }
} }
if v, ok := annotations[PanicThresholdPercentageAnnotationKey]; ok { if k, v, ok := PanicThresholdPercentageAnnotation.Get(m); ok {
if fv, err := strconv.ParseFloat(v, 64); err != nil { if fv, err := strconv.ParseFloat(v, 64); err != nil {
errs = errs.Also(apis.ErrInvalidValue(v, PanicThresholdPercentageAnnotationKey)) errs = errs.Also(apis.ErrInvalidValue(v, k))
} else if fv < PanicThresholdPercentageMin || fv > PanicThresholdPercentageMax { } else if fv < PanicThresholdPercentageMin || fv > PanicThresholdPercentageMax {
errs = errs.Also(apis.ErrOutOfBoundsValue(v, PanicThresholdPercentageMin, errs = errs.Also(apis.ErrOutOfBoundsValue(v, PanicThresholdPercentageMin,
PanicThresholdPercentageMax, PanicThresholdPercentageAnnotationKey)) PanicThresholdPercentageMax, k))
} }
} }
if v, ok := annotations[TargetAnnotationKey]; ok { if k, v, ok := TargetAnnotation.Get(m); ok {
if fv, err := strconv.ParseFloat(v, 64); err != nil || fv < TargetMin { if fv, err := strconv.ParseFloat(v, 64); err != nil || fv < TargetMin {
errs = errs.Also(apis.ErrGeneric(fmt.Sprintf("target %s should be at least %g", v, TargetMin), TargetAnnotationKey)) errs = errs.Also(apis.ErrGeneric(fmt.Sprintf("target %s should be at least %g", v, TargetMin), k))
} }
} }
if v, ok := annotations[TargetUtilizationPercentageKey]; ok { if k, v, ok := TargetUtilizationPercentageAnnotation.Get(m); ok {
if fv, err := strconv.ParseFloat(v, 64); err != nil { if fv, err := strconv.ParseFloat(v, 64); err != nil {
errs = errs.Also(apis.ErrInvalidValue(v, TargetUtilizationPercentageKey)) errs = errs.Also(apis.ErrInvalidValue(v, k))
} else if fv < 1 || fv > 100 { } else if fv < 1 || fv > 100 {
errs = errs.Also(apis.ErrOutOfBoundsValue(v, 1, 100, TargetUtilizationPercentageKey)) errs = errs.Also(apis.ErrOutOfBoundsValue(v, 1, 100, k))
} }
} }
if v, ok := annotations[TargetBurstCapacityKey]; ok { if k, v, ok := TargetBurstCapacityAnnotation.Get(m); ok {
if fv, err := strconv.ParseFloat(v, 64); err != nil || fv < 0 && fv != -1 { if fv, err := strconv.ParseFloat(v, 64); err != nil || fv < 0 && fv != -1 {
errs = errs.Also(apis.ErrInvalidValue(v, TargetBurstCapacityKey)) errs = errs.Also(apis.ErrInvalidValue(v, k))
} }
} }
return errs return errs
} }
func validateScaleDownDelay(annotations map[string]string) *apis.FieldError { func validateScaleDownDelay(m map[string]string) *apis.FieldError {
var errs *apis.FieldError var errs *apis.FieldError
if w, ok := annotations[ScaleDownDelayAnnotationKey]; ok { if k, v, ok := ScaleDownDelayAnnotation.Get(m); ok {
if d, err := time.ParseDuration(w); err != nil { if d, err := time.ParseDuration(v); err != nil {
errs = apis.ErrInvalidValue(w, ScaleDownDelayAnnotationKey) errs = apis.ErrInvalidValue(v, k)
} else if d < 0 || d > WindowMax { } else if d < 0 || d > WindowMax {
// Since we disallow windows longer than WindowMax, so we should limit this // Since we disallow windows longer than WindowMax, so we should limit this
// as well. // as well.
errs = apis.ErrOutOfBoundsValue(w, 0*time.Second, WindowMax, ScaleDownDelayAnnotationKey) errs = apis.ErrOutOfBoundsValue(v, 0*time.Second, WindowMax, k)
} else if d.Round(time.Second) != d { } else if d.Round(time.Second) != d {
errs = apis.ErrGeneric("must be specified with at most second precision", ScaleDownDelayAnnotationKey) errs = apis.ErrGeneric("must be specified with at most second precision", k)
} }
} }
return errs return errs
} }
func validateLastPodRetention(annotations map[string]string) *apis.FieldError { func validateLastPodRetention(m map[string]string) *apis.FieldError {
if w, ok := annotations[ScaleToZeroPodRetentionPeriodKey]; ok { if k, v, ok := ScaleToZeroPodRetentionPeriodAnnotation.Get(m); ok {
if d, err := time.ParseDuration(w); err != nil { if d, err := time.ParseDuration(v); err != nil {
return apis.ErrInvalidValue(w, ScaleToZeroPodRetentionPeriodKey) return apis.ErrInvalidValue(v, k)
} else if d < 0 || d > WindowMax { } else if d < 0 || d > WindowMax {
// Since we disallow windows longer than WindowMax, so we should limit this // Since we disallow windows longer than WindowMax, so we should limit this
// as well. // as well.
return apis.ErrOutOfBoundsValue(w, time.Duration(0), WindowMax, ScaleToZeroPodRetentionPeriodKey) return apis.ErrOutOfBoundsValue(v, time.Duration(0), WindowMax, k)
} }
} }
return nil return nil
} }
func validateWindow(annotations map[string]string) *apis.FieldError { func validateWindow(m map[string]string) *apis.FieldError {
if w, ok := annotations[WindowAnnotationKey]; ok { if _, v, ok := WindowAnnotation.Get(m); ok {
switch d, err := time.ParseDuration(w); { switch d, err := time.ParseDuration(v); {
case err != nil: case err != nil:
return apis.ErrInvalidValue(w, WindowAnnotationKey) return apis.ErrInvalidValue(v, WindowAnnotationKey)
case d < WindowMin || d > WindowMax: case d < WindowMin || d > WindowMax:
return apis.ErrOutOfBoundsValue(w, WindowMin, WindowMax, WindowAnnotationKey) return apis.ErrOutOfBoundsValue(v, WindowMin, WindowMax, WindowAnnotationKey)
case d.Truncate(time.Second) != d: case d.Truncate(time.Second) != d:
return apis.ErrGeneric("must be specified with at most second precision", WindowAnnotationKey) return apis.ErrGeneric("must be specified with at most second precision", WindowAnnotationKey)
} }
@ -170,48 +173,48 @@ func validateWindow(annotations map[string]string) *apis.FieldError {
return nil return nil
} }
func validateMinMaxScale(config *autoscalerconfig.Config, annotations map[string]string) *apis.FieldError { func validateMinMaxScale(config *autoscalerconfig.Config, m map[string]string) *apis.FieldError {
min, errs := getIntGE0(annotations, MinScaleAnnotationKey) min, errs := getIntGE0(m, MinScaleAnnotation)
max, err := getIntGE0(annotations, MaxScaleAnnotationKey) max, err := getIntGE0(m, MaxScaleAnnotation)
errs = errs.Also(err) errs = errs.Also(err)
if max != 0 && max < min { if max != 0 && max < min {
errs = errs.Also(&apis.FieldError{ errs = errs.Also(&apis.FieldError{
Message: fmt.Sprintf("maxScale=%d is less than minScale=%d", max, min), Message: fmt.Sprintf("max-scale=%d is less than min-scale=%d", max, min),
Paths: []string{MaxScaleAnnotationKey, MinScaleAnnotationKey}, Paths: []string{MaxScaleAnnotationKey, MinScaleAnnotationKey},
}) })
} }
if _, hasMaxScaleAnnotation := annotations[MaxScaleAnnotationKey]; hasMaxScaleAnnotation { if k, _, ok := MaxScaleAnnotation.Get(m); ok {
errs = errs.Also(validateMaxScaleWithinLimit(max, config.MaxScaleLimit)) errs = errs.Also(validateMaxScaleWithinLimit(k, max, config.MaxScaleLimit))
} }
return errs return errs
} }
func validateMaxScaleWithinLimit(maxScale, maxScaleLimit int32) (errs *apis.FieldError) { func validateMaxScaleWithinLimit(key string, maxScale, maxScaleLimit int32) (errs *apis.FieldError) {
if maxScaleLimit == 0 { if maxScaleLimit == 0 {
return nil return nil
} }
if maxScale > maxScaleLimit { if maxScale > maxScaleLimit {
errs = errs.Also(apis.ErrOutOfBoundsValue(maxScale, 1, maxScaleLimit, MaxScaleAnnotationKey)) errs = errs.Also(apis.ErrOutOfBoundsValue(maxScale, 1, maxScaleLimit, key))
} }
if maxScale == 0 { if maxScale == 0 {
errs = errs.Also(&apis.FieldError{ errs = errs.Also(&apis.FieldError{
Message: fmt.Sprint("maxScale=0 (unlimited), must be less than ", maxScaleLimit), Message: fmt.Sprint("max-scale=0 (unlimited), must be less than ", maxScaleLimit),
Paths: []string{MaxScaleAnnotationKey}, Paths: []string{key},
}) })
} }
return errs return errs
} }
func validateMetric(annotations map[string]string) *apis.FieldError { func validateMetric(m map[string]string) *apis.FieldError {
if metric, ok := annotations[MetricAnnotationKey]; ok { if _, metric, ok := MetricAnnotation.Get(m); ok {
classValue := KPA classValue := KPA
if c, ok := annotations[ClassAnnotationKey]; ok { if _, c, ok := ClassAnnotation.Get(m); ok {
classValue = c classValue = c
} }
switch classValue { switch classValue {
@ -234,11 +237,11 @@ func validateMetric(annotations map[string]string) *apis.FieldError {
return nil return nil
} }
func validateInitialScale(config *autoscalerconfig.Config, annotations map[string]string) *apis.FieldError { func validateInitialScale(config *autoscalerconfig.Config, m map[string]string) *apis.FieldError {
if initialScale, ok := annotations[InitialScaleAnnotationKey]; ok { if k, v, ok := InitialScaleAnnotation.Get(m); ok {
initScaleInt, err := strconv.Atoi(initialScale) initScaleInt, err := strconv.Atoi(v)
if err != nil || initScaleInt < 0 || (!config.AllowZeroInitialScale && initScaleInt == 0) { if err != nil || initScaleInt < 0 || (!config.AllowZeroInitialScale && initScaleInt == 0) {
return apis.ErrInvalidValue(initialScale, InitialScaleAnnotationKey) return apis.ErrInvalidValue(v, k)
} }
} }
return nil return nil

View File

@ -16,7 +16,11 @@ limitations under the License.
package autoscaling package autoscaling
import "time" import (
"time"
"knative.dev/pkg/kmap"
)
const ( const (
domain = ".knative.dev" domain = ".knative.dev"
@ -39,20 +43,21 @@ const (
// MinScaleAnnotationKey is the annotation to specify the minimum number of Pods // MinScaleAnnotationKey is the annotation to specify the minimum number of Pods
// the PodAutoscaler should provision. For example, // the PodAutoscaler should provision. For example,
// autoscaling.knative.dev/minScale: "1" // autoscaling.knative.dev/min-scale: "1"
MinScaleAnnotationKey = GroupName + "/minScale" MinScaleAnnotationKey = GroupName + "/min-scale"
// MaxScaleAnnotationKey is the annotation to specify the maximum number of Pods // MaxScaleAnnotationKey is the annotation to specify the maximum number of Pods
// the PodAutoscaler should provision. For example, // the PodAutoscaler should provision. For example,
// autoscaling.knative.dev/maxScale: "10" // autoscaling.knative.dev/max-scale: "10"
MaxScaleAnnotationKey = GroupName + "/maxScale" MaxScaleAnnotationKey = GroupName + "/max-scale"
// InitialScaleAnnotationKey is the annotation to specify the initial scale of // InitialScaleAnnotationKey is the annotation to specify the initial scale of
// a revision when a service is initially deployed. This number can be set to 0 iff // a revision when a service is initially deployed. This number can be set to 0 iff
// allow-zero-initial-scale of config-autoscaler is true. // allow-zero-initial-scale of config-autoscaler is true.
InitialScaleAnnotationKey = GroupName + "/initialScale" InitialScaleAnnotationKey = GroupName + "/initial-scale"
// ScaleDownDelayAnnotationKey is the annotation to specify a scale down delay. // ScaleDownDelayAnnotationKey is the annotation to specify a scale down delay.
ScaleDownDelayAnnotationKey = GroupName + "/scaleDownDelay" ScaleDownDelayAnnotationKey = GroupName + "/scale-down-delay"
// MetricAnnotationKey is the annotation to specify what metric the PodAutoscaler // MetricAnnotationKey is the annotation to specify what metric the PodAutoscaler
// should be scaled on. For example, // should be scaled on. For example,
@ -86,7 +91,7 @@ const (
// made the decision to scale to 0. // made the decision to scale to 0.
// This is the per-revision setting compliment to the // This is the per-revision setting compliment to the
// scale-to-zero-pod-retention-period global setting. // scale-to-zero-pod-retention-period global setting.
ScaleToZeroPodRetentionPeriodKey = GroupName + "/scaleToZeroPodRetentionPeriod" ScaleToZeroPodRetentionPeriodKey = GroupName + "/scale-to-zero-pod-retention-period"
// MetricAggregationAlgorithmKey is the annotation that can be used for selection // MetricAggregationAlgorithmKey is the annotation that can be used for selection
// of the algorithm to use for averaging metric data in the Autoscaler. // of the algorithm to use for averaging metric data in the Autoscaler.
@ -102,13 +107,21 @@ const (
// KPA will compute the decay multiplier automatically based on the window size // KPA will compute the decay multiplier automatically based on the window size
// and it is at least 0.2. This algorithm might not utilize all the values // and it is at least 0.2. This algorithm might not utilize all the values
// in the window, due to their coefficients being infinitesimal. // in the window, due to their coefficients being infinitesimal.
MetricAggregationAlgorithmKey = GroupName + "/metricAggregationAlgorithm" MetricAggregationAlgorithmKey = GroupName + "/metric-aggregation-algorithm"
// MetricAggregationAlgorithmLinear is the linear aggregation algorithm with all weights // MetricAggregationAlgorithmLinear is the linear aggregation algorithm with all weights
// equal to 1. // equal to 1.
MetricAggregationAlgorithmLinear = "linear" MetricAggregationAlgorithmLinear = "linear"
// MetricAggregationAlgorithmWeightedExponential is the weighted aggregation algorithm // MetricAggregationAlgorithmWeightedExponential is the weighted aggregation algorithm
// with exponentially decaying weights. // with exponentially decaying weights.
MetricAggregationAlgorithmWeightedExponential = "weightedExponential" MetricAggregationAlgorithmWeightedExponential = "weighted-exponential"
// MetricAggregationAlgorithmWeightedExponentialAlt is the alternate casing for MetricAggregationAlgorithmWeightedExponential
// Note: use the Metric.AggregationAlgorithm() method as it will normalize the casing
// and return MetricAggregationAlgorithmWeightedExponential
MetricAggregationAlgorithmWeightedExponentialAlt = "weightedExponential"
// WindowAnnotationKey is the annotation to specify the time // WindowAnnotationKey is the annotation to specify the time
// interval over which to calculate the average metric. Larger // interval over which to calculate the average metric. Larger
@ -136,7 +149,7 @@ const (
// desired target resource utilization for the revision. // desired target resource utilization for the revision.
// TargetUtilization is a percentage in the 1 <= TU <= 100 range. // TargetUtilization is a percentage in the 1 <= TU <= 100 range.
// This annotation takes precedence over the config map value. // This annotation takes precedence over the config map value.
TargetUtilizationPercentageKey = GroupName + "/targetUtilizationPercentage" TargetUtilizationPercentageKey = GroupName + "/target-utilization-percentage"
// TargetBurstCapacityKey specifies the desired burst capacity for the // TargetBurstCapacityKey specifies the desired burst capacity for the
// revision. Possible values are: // revision. Possible values are:
@ -144,7 +157,7 @@ const (
// 0 -- no TBC; // 0 -- no TBC;
// >0 -- actual TBC. // >0 -- actual TBC.
// <0 && != -1 -- an error. // <0 && != -1 -- an error.
TargetBurstCapacityKey = GroupName + "/targetBurstCapacity" TargetBurstCapacityKey = GroupName + "/target-burst-capacity"
// PanicWindowPercentageAnnotationKey is the annotation to // PanicWindowPercentageAnnotationKey is the annotation to
// specify the time interval over which to calculate the average // specify the time interval over which to calculate the average
@ -153,15 +166,16 @@ const (
// mode). Lower values make panic mode more sensitive. Note: // mode). Lower values make panic mode more sensitive. Note:
// Panic threshold can be overridden with the // Panic threshold can be overridden with the
// PanicThresholdPercentageAnnotationKey. For example, // PanicThresholdPercentageAnnotationKey. For example,
// autoscaling.knative.dev/panicWindowPercentage: "5.0" // autoscaling.knative.dev/panic-window-percentage: "5.0"
// autoscaling.knative.dev/panicThresholdPercentage: "150.0" // autoscaling.knative.dev/panic-threshold-percentage: "150.0"
// Only the kpa.autoscaling.knative.dev class autoscaler supports // Only the kpa.autoscaling.knative.dev class autoscaler supports
// the panicWindowPercentage annotation. // the panic-window-percentage annotation.
// Panic window is specified as a percentage to maintain the // Panic window is specified as a percentage to maintain the
// autoscaler's algorithm behavior when only the stable window is // autoscaler's algorithm behavior when only the stable window is
// specified. The panic window will change along with the stable // specified. The panic window will change along with the stable
// window at the default percentage. // window at the default percentage.
PanicWindowPercentageAnnotationKey = GroupName + "/panicWindowPercentage" PanicWindowPercentageAnnotationKey = GroupName + "/panic-window-percentage"
// PanicWindowPercentageMin is the minimum allowable panic window // PanicWindowPercentageMin is the minimum allowable panic window
// percentage. The autoscaler calculates desired replicas every 2 // percentage. The autoscaler calculates desired replicas every 2
// seconds (tick-interval in config-autoscaler), so a panic // seconds (tick-interval in config-autoscaler), so a panic
@ -182,11 +196,12 @@ const (
// in the panic window. The level is defined as a percentage of // in the panic window. The level is defined as a percentage of
// the metric target. Lower values make panic mode more // the metric target. Lower values make panic mode more
// sensitive. For example, // sensitive. For example,
// autoscaling.knative.dev/panicWindowPercentage: "5.0" // autoscaling.knative.dev/panic-window-percentage: "5.0"
// autoscaling.knative.dev/panicThresholdPercentage: "150.0" // autoscaling.knative.dev/panic-threshold-percentage: "150.0"
// Only the kpa.autoscaling.knative.dev class autoscaler supports // Only the kpa.autoscaling.knative.dev class autoscaler supports
// the panicThresholdPercentage annotation // the panicThresholdPercentage annotation
PanicThresholdPercentageAnnotationKey = GroupName + "/panicThresholdPercentage" PanicThresholdPercentageAnnotationKey = GroupName + "/panic-threshold-percentage"
// PanicThresholdPercentageMin is the minimum allowable panic // PanicThresholdPercentageMin is the minimum allowable panic
// threshold percentage. The KPA autoscaler's panic feature // threshold percentage. The KPA autoscaler's panic feature
// allows the autoscaler to be more responsive over a smaller // allows the autoscaler to be more responsive over a smaller
@ -202,3 +217,58 @@ const (
// but bounding from above. // but bounding from above.
PanicThresholdPercentageMax = 1000.0 PanicThresholdPercentageMax = 1000.0
) )
var (
ClassAnnotation = kmap.KeyPriority{
ClassAnnotationKey,
}
InitialScaleAnnotation = kmap.KeyPriority{
InitialScaleAnnotationKey,
GroupName + "/initialScale",
}
MaxScaleAnnotation = kmap.KeyPriority{
MaxScaleAnnotationKey,
GroupName + "/maxScale",
}
MetricAnnotation = kmap.KeyPriority{
MetricAnnotationKey,
}
MetricAggregationAlgorithmAnnotation = kmap.KeyPriority{
MetricAggregationAlgorithmKey,
GroupName + "/metricAggregationAlgorithm",
}
MinScaleAnnotation = kmap.KeyPriority{
MinScaleAnnotationKey,
GroupName + "/minScale",
}
PanicThresholdPercentageAnnotation = kmap.KeyPriority{
PanicThresholdPercentageAnnotationKey,
GroupName + "/panicThresholdPercentage",
}
PanicWindowPercentageAnnotation = kmap.KeyPriority{
PanicWindowPercentageAnnotationKey,
GroupName + "/panicWindowPercentage",
}
ScaleDownDelayAnnotation = kmap.KeyPriority{
ScaleDownDelayAnnotationKey,
GroupName + "/scaleDownDelay",
}
ScaleToZeroPodRetentionPeriodAnnotation = kmap.KeyPriority{
ScaleToZeroPodRetentionPeriodKey,
GroupName + "/scaleToZeroPodRetentionPeriod",
}
TargetAnnotation = kmap.KeyPriority{
TargetAnnotationKey,
}
TargetBurstCapacityAnnotation = kmap.KeyPriority{
TargetBurstCapacityKey,
GroupName + "/targetBurstCapacity",
}
TargetUtilizationPercentageAnnotation = kmap.KeyPriority{
TargetUtilizationPercentageKey,
GroupName + "/targetUtilizationPercentage",
}
WindowAnnotation = kmap.KeyPriority{
WindowAnnotationKey,
}
)

View File

@ -19,6 +19,7 @@ package v1alpha1
import ( import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"knative.dev/pkg/apis" "knative.dev/pkg/apis"
"knative.dev/serving/pkg/apis/autoscaling"
) )
const ( const (
@ -74,3 +75,14 @@ func (m *Metric) IsReady() bool {
return ms.ObservedGeneration == m.Generation && return ms.ObservedGeneration == m.Generation &&
ms.GetCondition(MetricConditionReady).IsTrue() ms.GetCondition(MetricConditionReady).IsTrue()
} }
func (m *Metric) AggregationAlgorithm() string {
if _, s, ok := autoscaling.MetricAggregationAlgorithmAnnotation.Get(m.Annotations); ok {
// Normalize and use the regular casing
if s == autoscaling.MetricAggregationAlgorithmWeightedExponentialAlt {
return autoscaling.MetricAggregationAlgorithmWeightedExponential
}
return s
}
return ""
}

View File

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"knative.dev/pkg/apis" "knative.dev/pkg/apis"
"knative.dev/pkg/kmap"
"knative.dev/serving/pkg/apis/autoscaling" "knative.dev/serving/pkg/apis/autoscaling"
"knative.dev/serving/pkg/autoscaler/config/autoscalerconfig" "knative.dev/serving/pkg/autoscaler/config/autoscalerconfig"
) )
@ -63,16 +64,16 @@ func (pa *PodAutoscaler) Metric() string {
return defaultMetric(pa.Class()) return defaultMetric(pa.Class())
} }
func (pa *PodAutoscaler) annotationInt32(key string) (int32, bool) { func (pa *PodAutoscaler) annotationInt32(k kmap.KeyPriority) (int32, bool) {
if s, ok := pa.Annotations[key]; ok { if _, s, ok := k.Get(pa.Annotations); ok {
i, err := strconv.ParseInt(s, 10, 32) i, err := strconv.ParseInt(s, 10, 32)
return int32(i), err == nil return int32(i), err == nil
} }
return 0, false return 0, false
} }
func (pa *PodAutoscaler) annotationFloat64(key string) (float64, bool) { func (pa *PodAutoscaler) annotationFloat64(k kmap.KeyPriority) (float64, bool) {
if s, ok := pa.Annotations[key]; ok { if _, s, ok := k.Get(pa.Annotations); ok {
f, err := strconv.ParseFloat(s, 64) f, err := strconv.ParseFloat(s, 64)
return f, err == nil return f, err == nil
} }
@ -87,13 +88,13 @@ func (pa *PodAutoscaler) ScaleBounds(asConfig *autoscalerconfig.Config) (int32,
var min int32 var min int32
if pa.Spec.Reachability != ReachabilityUnreachable { if pa.Spec.Reachability != ReachabilityUnreachable {
min = asConfig.MinScale min = asConfig.MinScale
if paMin, ok := pa.annotationInt32(autoscaling.MinScaleAnnotationKey); ok { if paMin, ok := pa.annotationInt32(autoscaling.MinScaleAnnotation); ok {
min = paMin min = paMin
} }
} }
max := asConfig.MaxScale max := asConfig.MaxScale
if paMax, ok := pa.annotationInt32(autoscaling.MaxScaleAnnotationKey); ok { if paMax, ok := pa.annotationInt32(autoscaling.MaxScaleAnnotation); ok {
max = paMax max = paMax
} }
@ -102,13 +103,13 @@ func (pa *PodAutoscaler) ScaleBounds(asConfig *autoscalerconfig.Config) (int32,
// Target returns the target annotation value or false if not present, or invalid. // Target returns the target annotation value or false if not present, or invalid.
func (pa *PodAutoscaler) Target() (float64, bool) { func (pa *PodAutoscaler) Target() (float64, bool) {
return pa.annotationFloat64(autoscaling.TargetAnnotationKey) return pa.annotationFloat64(autoscaling.TargetAnnotation)
} }
// TargetUtilization returns the target utilization percentage as a fraction, if // TargetUtilization returns the target utilization percentage as a fraction, if
// the corresponding annotation is set. // the corresponding annotation is set.
func (pa *PodAutoscaler) TargetUtilization() (float64, bool) { func (pa *PodAutoscaler) TargetUtilization() (float64, bool) {
if tu, ok := pa.annotationFloat64(autoscaling.TargetUtilizationPercentageKey); ok { if tu, ok := pa.annotationFloat64(autoscaling.TargetUtilizationPercentageAnnotation); ok {
return tu / 100, true return tu / 100, true
} }
return 0, false return 0, false
@ -117,11 +118,11 @@ func (pa *PodAutoscaler) TargetUtilization() (float64, bool) {
// TargetBC returns the target burst capacity, if the corresponding annotation is set. // TargetBC returns the target burst capacity, if the corresponding annotation is set.
func (pa *PodAutoscaler) TargetBC() (float64, bool) { func (pa *PodAutoscaler) TargetBC() (float64, bool) {
// The value is validated in the webhook. // The value is validated in the webhook.
return pa.annotationFloat64(autoscaling.TargetBurstCapacityKey) return pa.annotationFloat64(autoscaling.TargetBurstCapacityAnnotation)
} }
func (pa *PodAutoscaler) annotationDuration(key string) (time.Duration, bool) { func (pa *PodAutoscaler) annotationDuration(k kmap.KeyPriority) (time.Duration, bool) {
if s, ok := pa.Annotations[key]; ok { if _, s, ok := k.Get(pa.Annotations); ok {
d, err := time.ParseDuration(s) d, err := time.ParseDuration(s)
return d, err == nil return d, err == nil
} }
@ -132,37 +133,37 @@ func (pa *PodAutoscaler) annotationDuration(key string) (time.Duration, bool) {
// or false if not present. // or false if not present.
func (pa *PodAutoscaler) ScaleToZeroPodRetention() (time.Duration, bool) { func (pa *PodAutoscaler) ScaleToZeroPodRetention() (time.Duration, bool) {
// The value is validated in the webhook. // The value is validated in the webhook.
return pa.annotationDuration(autoscaling.ScaleToZeroPodRetentionPeriodKey) return pa.annotationDuration(autoscaling.ScaleToZeroPodRetentionPeriodAnnotation)
} }
// Window returns the window annotation value, or false if not present. // Window returns the window annotation value, or false if not present.
func (pa *PodAutoscaler) Window() (time.Duration, bool) { func (pa *PodAutoscaler) Window() (time.Duration, bool) {
// The value is validated in the webhook. // The value is validated in the webhook.
return pa.annotationDuration(autoscaling.WindowAnnotationKey) return pa.annotationDuration(autoscaling.WindowAnnotation)
} }
// ScaleDownDelay returns the scale down delay annotation, or false if not present. // ScaleDownDelay returns the scale down delay annotation, or false if not present.
func (pa *PodAutoscaler) ScaleDownDelay() (time.Duration, bool) { func (pa *PodAutoscaler) ScaleDownDelay() (time.Duration, bool) {
// The value is validated in the webhook. // The value is validated in the webhook.
return pa.annotationDuration(autoscaling.ScaleDownDelayAnnotationKey) return pa.annotationDuration(autoscaling.ScaleDownDelayAnnotation)
} }
// PanicWindowPercentage returns the panic window annotation value, or false if not present. // PanicWindowPercentage returns the panic window annotation value, or false if not present.
func (pa *PodAutoscaler) PanicWindowPercentage() (percentage float64, ok bool) { func (pa *PodAutoscaler) PanicWindowPercentage() (percentage float64, ok bool) {
// The value is validated in the webhook. // The value is validated in the webhook.
return pa.annotationFloat64(autoscaling.PanicWindowPercentageAnnotationKey) return pa.annotationFloat64(autoscaling.PanicWindowPercentageAnnotation)
} }
// PanicThresholdPercentage returns the panic threshold annotation value, or false if not present. // PanicThresholdPercentage returns the panic threshold annotation value, or false if not present.
func (pa *PodAutoscaler) PanicThresholdPercentage() (percentage float64, ok bool) { func (pa *PodAutoscaler) PanicThresholdPercentage() (percentage float64, ok bool) {
// The value is validated in the webhook. // The value is validated in the webhook.
return pa.annotationFloat64(autoscaling.PanicThresholdPercentageAnnotationKey) return pa.annotationFloat64(autoscaling.PanicThresholdPercentageAnnotation)
} }
// InitialScale returns the initial scale on the revision if present, or false if not present. // InitialScale returns the initial scale on the revision if present, or false if not present.
func (pa *PodAutoscaler) InitialScale() (int32, bool) { func (pa *PodAutoscaler) InitialScale() (int32, bool) {
// The value is validated in the webhook. // The value is validated in the webhook.
return pa.annotationInt32(autoscaling.InitialScaleAnnotationKey) return pa.annotationInt32(autoscaling.InitialScaleAnnotation)
} }
// IsReady returns true if the Status condition PodAutoscalerConditionReady // IsReady returns true if the Status condition PodAutoscalerConditionReady

View File

@ -50,25 +50,25 @@ func ValidateObjectMetadata(ctx context.Context, meta metav1.Object, allowAutosc
// ValidateRolloutDurationAnnotation validates the rollout duration annotation. // ValidateRolloutDurationAnnotation validates the rollout duration annotation.
// This annotation can be set on either service or route objects. // This annotation can be set on either service or route objects.
func ValidateRolloutDurationAnnotation(annos map[string]string) (errs *apis.FieldError) { func ValidateRolloutDurationAnnotation(annos map[string]string) (errs *apis.FieldError) {
if v := annos[RolloutDurationKey]; v != "" { if k, v, _ := RolloutDurationAnnotation.Get(annos); v != "" {
// Parse as duration. // Parse as duration.
d, err := time.ParseDuration(v) d, err := time.ParseDuration(v)
if err != nil { if err != nil {
return errs.Also(apis.ErrInvalidValue(v, RolloutDurationKey)) return errs.Also(apis.ErrInvalidValue(v, k))
} }
// Validate that it has second precision. // Validate that it has second precision.
if d.Round(time.Second) != d { if d.Round(time.Second) != d {
return errs.Also(&apis.FieldError{ return errs.Also(&apis.FieldError{
// Even if tempting %v won't work here, since it might output the value spelled differently. // Even if tempting %v won't work here, since it might output the value spelled differently.
Message: fmt.Sprintf("rolloutDuration=%s is not at second precision", v), Message: fmt.Sprintf("rollout-duration=%s is not at second precision", v),
Paths: []string{RolloutDurationKey}, Paths: []string{k},
}) })
} }
// And positive. // And positive.
if d < 0 { if d < 0 {
return errs.Also(&apis.FieldError{ return errs.Also(&apis.FieldError{
Message: fmt.Sprintf("rolloutDuration=%s must be positive", v), Message: fmt.Sprintf("rollout-duration=%s must be positive", v),
Paths: []string{RolloutDurationKey}, Paths: []string{k},
}) })
} }
} }

View File

@ -16,7 +16,10 @@ limitations under the License.
package serving package serving
import "k8s.io/apimachinery/pkg/runtime/schema" import (
"k8s.io/apimachinery/pkg/runtime/schema"
"knative.dev/pkg/kmap"
)
const ( const (
// GroupName is the group name for knative labels and annotations // GroupName is the group name for knative labels and annotations
@ -55,7 +58,7 @@ const (
// of the rollout of the latest revision. The value must be a valid positive // of the rollout of the latest revision. The value must be a valid positive
// Golang time.Duration value serialized to string. // Golang time.Duration value serialized to string.
// The value can be specified with at most with a second precision. // The value can be specified with at most with a second precision.
RolloutDurationKey = GroupName + "/rolloutDuration" RolloutDurationKey = GroupName + "/rollout-duration"
// RoutingStateLabelKey is the label attached to a Revision indicating // RoutingStateLabelKey is the label attached to a Revision indicating
// its state in relation to serving a Route. // its state in relation to serving a Route.
@ -111,9 +114,9 @@ const (
// last updated the resource. // last updated the resource.
UpdaterAnnotation = GroupName + "/lastModifier" UpdaterAnnotation = GroupName + "/lastModifier"
// QueueSideCarResourcePercentageAnnotation is the percentage of user container resources to be used for queue-proxy // QueueSidecarResourcePercentageAnnotationKey is the percentage of user container resources to be used for queue-proxy
// It has to be in [0.1,100] // It has to be in [0.1,100]
QueueSideCarResourcePercentageAnnotation = "queue.sidecar." + GroupName + "/resourcePercentage" QueueSidecarResourcePercentageAnnotationKey = "queue.sidecar." + GroupName + "/resource-percentage"
// VisibilityClusterLocal is the label value for VisibilityLabelKey // VisibilityClusterLocal is the label value for VisibilityLabelKey
// that will result to the Route/KService getting a cluster local // that will result to the Route/KService getting a cluster local
@ -146,3 +149,14 @@ var (
Resource: "routes", Resource: "routes",
} }
) )
var (
RolloutDurationAnnotation = kmap.KeyPriority{
RolloutDurationKey,
GroupName + "/rolloutDuration",
}
QueueSidecarResourcePercentageAnnotation = kmap.KeyPriority{
QueueSidecarResourcePercentageAnnotationKey,
"queue.sidecar." + GroupName + "/resourcePercentage",
}
)

View File

@ -178,22 +178,20 @@ func validateTimeoutSeconds(ctx context.Context, timeoutSeconds int64) *apis.Fie
} }
// validateQueueSidecarAnnotation validates QueueSideCarResourcePercentageAnnotation // validateQueueSidecarAnnotation validates QueueSideCarResourcePercentageAnnotation
func validateQueueSidecarAnnotation(annotations map[string]string) *apis.FieldError { func validateQueueSidecarAnnotation(m map[string]string) *apis.FieldError {
if len(annotations) == 0 { if len(m) == 0 {
return nil return nil
} }
v, ok := annotations[serving.QueueSideCarResourcePercentageAnnotation] k, v, ok := serving.QueueSidecarResourcePercentageAnnotation.Get(m)
if !ok { if !ok {
return nil return nil
} }
value, err := strconv.ParseFloat(v, 64) value, err := strconv.ParseFloat(v, 64)
if err != nil { if err != nil {
return apis.ErrInvalidValue(v, apis.CurrentField). return apis.ErrInvalidValue(v, apis.CurrentField).ViaKey(k)
ViaKey(serving.QueueSideCarResourcePercentageAnnotation)
} }
if value < 0.1 || value > 100 { if value < 0.1 || value > 100 {
return apis.ErrOutOfBoundsValue(value, 0.1, 100.0, apis.CurrentField). return apis.ErrOutOfBoundsValue(value, 0.1, 100.0, apis.CurrentField).ViaKey(k)
ViaKey(serving.QueueSideCarResourcePercentageAnnotation)
} }
return nil return nil
} }

View File

@ -64,7 +64,7 @@ func (r *Route) IsFailed() bool {
// annotation. // annotation.
// 0 is returned if missing or cannot be parsed. // 0 is returned if missing or cannot be parsed.
func (r *Route) RolloutDuration() time.Duration { func (r *Route) RolloutDuration() time.Duration {
if v, ok := r.Annotations[serving.RolloutDurationKey]; ok && v != "" { if _, v, ok := serving.RolloutDurationAnnotation.Get(r.Annotations); ok && v != "" {
// WH should've declined all the invalid values for this annotation. // WH should've declined all the invalid values for this annotation.
if d, err := time.ParseDuration(v); err == nil { if d, err := time.ParseDuration(v); err == nil {
return d return d

8
vendor/modules.txt vendored
View File

@ -731,7 +731,7 @@ k8s.io/utils/buffer
k8s.io/utils/integer k8s.io/utils/integer
k8s.io/utils/pointer k8s.io/utils/pointer
k8s.io/utils/trace k8s.io/utils/trace
# knative.dev/eventing v0.27.1-0.20211123070249-2cda8f40b5d9 # knative.dev/eventing v0.27.1-0.20211123205351-820db20be4b2
## explicit ## explicit
knative.dev/eventing/pkg/apis/config knative.dev/eventing/pkg/apis/config
knative.dev/eventing/pkg/apis/duck knative.dev/eventing/pkg/apis/duck
@ -760,7 +760,7 @@ knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2/fake
# knative.dev/hack v0.0.0-20211122162614-813559cefdda # knative.dev/hack v0.0.0-20211122162614-813559cefdda
## explicit ## explicit
knative.dev/hack knative.dev/hack
# knative.dev/networking v0.0.0-20211123024050-aa82452902be # knative.dev/networking v0.0.0-20211124064027-ea794f17c1bf
## explicit ## explicit
knative.dev/networking/pkg knative.dev/networking/pkg
knative.dev/networking/pkg/apis/networking knative.dev/networking/pkg/apis/networking
@ -768,7 +768,7 @@ knative.dev/networking/pkg/apis/networking/v1alpha1
knative.dev/networking/pkg/client/clientset/versioned knative.dev/networking/pkg/client/clientset/versioned
knative.dev/networking/pkg/client/clientset/versioned/scheme knative.dev/networking/pkg/client/clientset/versioned/scheme
knative.dev/networking/pkg/client/clientset/versioned/typed/networking/v1alpha1 knative.dev/networking/pkg/client/clientset/versioned/typed/networking/v1alpha1
# knative.dev/pkg v0.0.0-20211123074649-0fae0afc10ad # knative.dev/pkg v0.0.0-20211123135150-787aec59e70a
## explicit ## explicit
knative.dev/pkg/apis knative.dev/pkg/apis
knative.dev/pkg/apis/duck knative.dev/pkg/apis/duck
@ -818,7 +818,7 @@ knative.dev/pkg/tracing/config
knative.dev/pkg/tracing/propagation knative.dev/pkg/tracing/propagation
knative.dev/pkg/tracing/propagation/tracecontextb3 knative.dev/pkg/tracing/propagation/tracecontextb3
knative.dev/pkg/tracker knative.dev/pkg/tracker
# knative.dev/serving v0.27.1-0.20211123120750-26c7dc6ccc53 # knative.dev/serving v0.27.1-0.20211124064027-e6f8e414ac9e
## explicit ## explicit
knative.dev/serving/pkg/apis/autoscaling knative.dev/serving/pkg/apis/autoscaling
knative.dev/serving/pkg/apis/autoscaling/v1alpha1 knative.dev/serving/pkg/apis/autoscaling/v1alpha1