feature(serving): Add --autoscale-window (#614)

* feature(serving): Add --autoscale-window

Fixes #613

* chore: Update help-text for --autoscale-window

* chore: Add missing generated files
This commit is contained in:
Roland Huß 2020-01-22 09:18:23 +01:00 committed by Knative Prow Robot
parent 9fd763e5dd
commit 5001dcdc16
8 changed files with 121 additions and 57 deletions

View File

@ -42,31 +42,32 @@ kn service create NAME --image IMAGE [flags]
### Options ### Options
``` ```
--annotation stringArray Service annotation to set. name=value; you may provide this flag any number of times to set multiple annotations. To unset, specify the annotation name followed by a "-" (e.g., name-). --annotation stringArray Service annotation to set. name=value; you may provide this flag any number of times to set multiple annotations. To unset, specify the annotation name followed by a "-" (e.g., name-).
--async Create service and don't wait for it to become ready. --async Create service and don't wait for it to become ready.
--concurrency-limit int Hard Limit of concurrent requests to be processed by a single replica. --autoscale-window string Duration to look back for making auto-scaling decisions. The service is scaled to zero if no request was received in during that time. (eg: 10s)
--concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given. --concurrency-limit int Hard Limit of concurrent requests to be processed by a single replica.
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-). --concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-. -e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
--force Create service forcefully, replaces existing service if any. --env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
-h, --help help for create --force Create service forcefully, replaces existing service if any.
--image string Image to run. -h, --help help for create
-l, --label stringArray Service label to set. name=value; you may provide this flag any number of times to set multiple labels. To unset, specify the label name followed by a "-" (e.g., name-). --image string Image to run.
--limits-cpu string The limits on the requested CPU (e.g., 1000m). -l, --label stringArray Service label to set. name=value; you may provide this flag any number of times to set multiple labels. To unset, specify the label name followed by a "-" (e.g., name-).
--limits-memory string The limits on the requested memory (e.g., 1024Mi). --limits-cpu string The limits on the requested CPU (e.g., 1000m).
--lock-to-digest keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision) (default true) --limits-memory string The limits on the requested memory (e.g., 1024Mi).
--max-scale int Maximal number of replicas. --lock-to-digest keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision) (default true)
--min-scale int Minimal number of replicas. --max-scale int Maximal number of replicas.
--mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume. --min-scale int Minimal number of replicas.
-n, --namespace string Specify the namespace to operate in. --mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
--no-lock-to-digest do not keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision) -n, --namespace string Specify the namespace to operate in.
-p, --port int32 The port where application listens on. --no-lock-to-digest do not keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision)
--requests-cpu string The requested CPU (e.g., 250m). -p, --port int32 The port where application listens on.
--requests-memory string The requested memory (e.g., 64Mi). --requests-cpu string The requested CPU (e.g., 250m).
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}") --requests-memory string The requested memory (e.g., 64Mi).
--service-account string Service account name to set. Empty service account name will result to clear the service account. --revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}")
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-. --service-account string Service account name to set. Empty service account name will result to clear the service account.
--wait-timeout int Seconds to wait before giving up on waiting for service to be ready. (default 600) --volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
--wait-timeout int Seconds to wait before giving up on waiting for service to be ready. (default 600)
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

View File

@ -38,33 +38,34 @@ kn service update NAME [flags]
### Options ### Options
``` ```
--annotation stringArray Service annotation to set. name=value; you may provide this flag any number of times to set multiple annotations. To unset, specify the annotation name followed by a "-" (e.g., name-). --annotation stringArray Service annotation to set. name=value; you may provide this flag any number of times to set multiple annotations. To unset, specify the annotation name followed by a "-" (e.g., name-).
--async Update service and don't wait for it to become ready. --async Update service and don't wait for it to become ready.
--concurrency-limit int Hard Limit of concurrent requests to be processed by a single replica. --autoscale-window string Duration to look back for making auto-scaling decisions. The service is scaled to zero if no request was received in during that time. (eg: 10s)
--concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given. --concurrency-limit int Hard Limit of concurrent requests to be processed by a single replica.
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-). --concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.
--env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-. -e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
-h, --help help for update --env-from stringArray Add environment variables from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret:). Example: --env-from cm:myconfigmap or --env-from secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --env-from cm:myconfigmap-.
--image string Image to run. -h, --help help for update
-l, --label stringArray Service label to set. name=value; you may provide this flag any number of times to set multiple labels. To unset, specify the label name followed by a "-" (e.g., name-). --image string Image to run.
--limits-cpu string The limits on the requested CPU (e.g., 1000m). -l, --label stringArray Service label to set. name=value; you may provide this flag any number of times to set multiple labels. To unset, specify the label name followed by a "-" (e.g., name-).
--limits-memory string The limits on the requested memory (e.g., 1024Mi). --limits-cpu string The limits on the requested CPU (e.g., 1000m).
--lock-to-digest keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision) (default true) --limits-memory string The limits on the requested memory (e.g., 1024Mi).
--max-scale int Maximal number of replicas. --lock-to-digest keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision) (default true)
--min-scale int Minimal number of replicas. --max-scale int Maximal number of replicas.
--mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume. --min-scale int Minimal number of replicas.
-n, --namespace string Specify the namespace to operate in. --mount stringArray Mount a ConfigMap (prefix cm: or config-map:), a Secret (prefix secret: or sc:), or an existing Volume (without any prefix) on the specified directory. Example: --mount /mydir=cm:myconfigmap, --mount /mydir=secret:mysecret, or --mount /mydir=myvolume. When a configmap or a secret is specified, a corresponding volume is automatically generated. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
--no-lock-to-digest do not keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision) -n, --namespace string Specify the namespace to operate in.
-p, --port int32 The port where application listens on. --no-lock-to-digest do not keep the running image for the service constant when not explicitly specifying the image. (--no-lock-to-digest pulls the image tag afresh with each new revision)
--requests-cpu string The requested CPU (e.g., 250m). -p, --port int32 The port where application listens on.
--requests-memory string The requested memory (e.g., 64Mi). --requests-cpu string The requested CPU (e.g., 250m).
--revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}") --requests-memory string The requested memory (e.g., 64Mi).
--service-account string Service account name to set. Empty service account name will result to clear the service account. --revision-name string The revision name to set. Must start with the service name and a dash as a prefix. Empty revision name will result in the server generating a name for the revision. Accepts golang templates, allowing {{.Service}} for the service name, {{.Generation}} for the generation, and {{.Random [n]}} for n random consonants. (default "{{.Service}}-{{.Random 5}}-{{.Generation}}")
--tag strings Set tag (format: --tag revisionRef=tagName) where revisionRef can be a revision or '@latest' string representing latest ready revision. This flag can be specified multiple times. --service-account string Service account name to set. Empty service account name will result to clear the service account.
--traffic strings Set traffic distribution (format: --traffic revisionRef=percent) where revisionRef can be a revision or a tag or '@latest' string representing latest ready revision. This flag can be given multiple times with percent summing up to 100%. --tag strings Set tag (format: --tag revisionRef=tagName) where revisionRef can be a revision or '@latest' string representing latest ready revision. This flag can be specified multiple times.
--untag strings Untag revision (format: --untag tagName). This flag can be specified multiple times. --traffic strings Set traffic distribution (format: --traffic revisionRef=percent) where revisionRef can be a revision or a tag or '@latest' string representing latest ready revision. This flag can be given multiple times with percent summing up to 100%.
--volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-. --untag strings Untag revision (format: --untag tagName). This flag can be specified multiple times.
--wait-timeout int Seconds to wait before giving up on waiting for service to be ready. (default 600) --volume stringArray Add a volume from a ConfigMap (prefix cm: or config-map:) or a Secret (prefix secret: or sc:). Example: --volume myvolume=cm:myconfigmap or --volume myvolume=secret:mysecret. You can use this flag multiple times. To unset a ConfigMap/Secret reference, append "-" to the name, e.g. --volume myvolume-.
--wait-timeout int Seconds to wait before giving up on waiting for service to be ready. (default 600)
``` ```
### Options inherited from parent commands ### Options inherited from parent commands

View File

@ -129,7 +129,8 @@ func describe(w io.Writer, revision *v1alpha1.Revision, service *v1alpha1.Servic
func WriteConcurrencyOptions(dw printers.PrefixWriter, revision *v1alpha1.Revision) { func WriteConcurrencyOptions(dw printers.PrefixWriter, revision *v1alpha1.Revision) {
target := clientserving.ConcurrencyTarget(&revision.ObjectMeta) target := clientserving.ConcurrencyTarget(&revision.ObjectMeta)
limit := revision.Spec.ContainerConcurrency limit := revision.Spec.ContainerConcurrency
if target != nil || limit != nil && *limit != 0 { autoscaleWindow := clientserving.AutoscaleWindow(&revision.ObjectMeta)
if target != nil || limit != nil && *limit != 0 || autoscaleWindow != "" {
section := dw.WriteAttribute("Concurrency", "") section := dw.WriteAttribute("Concurrency", "")
if limit != nil && *limit != 0 { if limit != nil && *limit != 0 {
section.WriteAttribute("Limit", strconv.FormatInt(int64(*limit), 10)) section.WriteAttribute("Limit", strconv.FormatInt(int64(*limit), 10))
@ -137,7 +138,11 @@ func WriteConcurrencyOptions(dw printers.PrefixWriter, revision *v1alpha1.Revisi
if target != nil { if target != nil {
section.WriteAttribute("Target", strconv.Itoa(*target)) section.WriteAttribute("Target", strconv.Itoa(*target))
} }
if autoscaleWindow != "" {
section.WriteAttribute("Window", autoscaleWindow)
}
} }
} }
// Write the image attribute (with // Write the image attribute (with

View File

@ -41,6 +41,7 @@ type ConfigurationEditFlags struct {
MaxScale int MaxScale int
ConcurrencyTarget int ConcurrencyTarget int
ConcurrencyLimit int ConcurrencyLimit int
AutoscaleWindow string
Port int32 Port int32
Labels []string Labels []string
NamePrefix string NamePrefix string
@ -113,6 +114,8 @@ func (p *ConfigurationEditFlags) addSharedFlags(command *cobra.Command) {
p.markFlagMakesRevision("min-scale") p.markFlagMakesRevision("min-scale")
command.Flags().IntVar(&p.MaxScale, "max-scale", 0, "Maximal number of replicas.") command.Flags().IntVar(&p.MaxScale, "max-scale", 0, "Maximal number of replicas.")
p.markFlagMakesRevision("max-scale") p.markFlagMakesRevision("max-scale")
command.Flags().StringVar(&p.AutoscaleWindow, "autoscale-window", "", "Duration to look back for making auto-scaling decisions. The service is scaled to zero if no request was received in during that time. (eg: 10s)")
p.markFlagMakesRevision("autoscale-window")
command.Flags().IntVar(&p.ConcurrencyTarget, "concurrency-target", 0, command.Flags().IntVar(&p.ConcurrencyTarget, "concurrency-target", 0,
"Recommendation for when to scale up based on the concurrent number of incoming request. "+ "Recommendation for when to scale up based on the concurrent number of incoming request. "+
"Defaults to --concurrency-limit when given.") "Defaults to --concurrency-limit when given.")
@ -290,6 +293,13 @@ func (p *ConfigurationEditFlags) Apply(
} }
} }
if cmd.Flags().Changed("autoscale-window") {
err = servinglib.UpdateAutoscaleWindow(template, p.AutoscaleWindow)
if err != nil {
return err
}
}
if cmd.Flags().Changed("concurrency-target") { if cmd.Flags().Changed("concurrency-target") {
err = servinglib.UpdateConcurrencyTarget(template, p.ConcurrencyTarget) err = servinglib.UpdateConcurrencyTarget(template, p.ConcurrencyTarget)
if err != nil { if err != nil {

View File

@ -21,6 +21,7 @@ import (
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"time"
"unicode" "unicode"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
@ -183,6 +184,15 @@ func UpdateMaxScale(template *servingv1alpha1.RevisionTemplateSpec, max int) err
return UpdateRevisionTemplateAnnotation(template, autoscaling.MaxScaleAnnotationKey, strconv.Itoa(max)) return UpdateRevisionTemplateAnnotation(template, autoscaling.MaxScaleAnnotationKey, strconv.Itoa(max))
} }
// UpdateAutoscaleWindow updates the autoscale window annotation
func UpdateAutoscaleWindow(template *servingv1alpha1.RevisionTemplateSpec, window string) error {
_, err := time.ParseDuration(window)
if err != nil {
return fmt.Errorf("invalid duration for 'autoscale-window': %v", err)
}
return UpdateRevisionTemplateAnnotation(template, autoscaling.WindowAnnotationKey, window)
}
// UpdateConcurrencyTarget updates container concurrency annotation // UpdateConcurrencyTarget updates container concurrency annotation
func UpdateConcurrencyTarget(template *servingv1alpha1.RevisionTemplateSpec, target int) error { func UpdateConcurrencyTarget(template *servingv1alpha1.RevisionTemplateSpec, target int) error {
return UpdateRevisionTemplateAnnotation(template, autoscaling.TargetAnnotationKey, strconv.Itoa(target)) return UpdateRevisionTemplateAnnotation(template, autoscaling.TargetAnnotationKey, strconv.Itoa(target))

View File

@ -225,7 +225,7 @@ func TestUpdateMinScale(t *testing.T) {
err := UpdateMinScale(template, 10) err := UpdateMinScale(template, 10)
assert.NilError(t, err) assert.NilError(t, err)
// Verify update is successful or not // Verify update is successful or not
checkAnnotationValue(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, "minScale")
@ -236,18 +236,29 @@ func TestUpdateMaxScale(t *testing.T) {
err := UpdateMaxScale(template, 10) err := UpdateMaxScale(template, 10)
assert.NilError(t, err) assert.NilError(t, err)
// Verify update is successful or not // Verify update is successful or not
checkAnnotationValue(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, "maxScale")
} }
func TestAutoscaleWindow(t *testing.T) {
template, _ := getV1alpha1RevisionTemplateWithOldFields()
err := UpdateAutoscaleWindow(template, "10s")
assert.NilError(t, err)
// Verify update is successful or not
checkAnnotationValue(t, template, autoscaling.WindowAnnotationKey, "10s")
// Update with invalid value
err = UpdateAutoscaleWindow(template, "blub")
assert.Check(t, util.ContainsAll(err.Error(), "invalid duration", "autoscale-window"))
}
func TestUpdateConcurrencyTarget(t *testing.T) { func TestUpdateConcurrencyTarget(t *testing.T) {
template, _ := getV1alpha1RevisionTemplateWithOldFields() template, _ := getV1alpha1RevisionTemplateWithOldFields()
err := UpdateConcurrencyTarget(template, 10) err := UpdateConcurrencyTarget(template, 10)
assert.NilError(t, err) assert.NilError(t, err)
// Verify update is successful or not // Verify update is successful or not
checkAnnotationValue(t, template, autoscaling.TargetAnnotationKey, 10) checkAnnotationValueInt(t, template, autoscaling.TargetAnnotationKey, 10)
// Update with invalid value // Update with invalid value
err = UpdateConcurrencyTarget(template, -1) err = UpdateConcurrencyTarget(template, -1)
assert.ErrorContains(t, err, "invalid") assert.ErrorContains(t, err, "invalid")
@ -708,13 +719,20 @@ func assertNoV1alpha1(t *testing.T, template *servingv1alpha1.RevisionTemplateSp
} }
} }
func checkAnnotationValue(t *testing.T, template *servingv1alpha1.RevisionTemplateSpec, key string, value int) { func checkAnnotationValueInt(t *testing.T, template *servingv1alpha1.RevisionTemplateSpec, key string, value int) {
anno := template.GetAnnotations() anno := template.GetAnnotations()
if v, ok := anno[key]; !ok && v != strconv.Itoa(value) { if v, ok := anno[key]; !ok && v != strconv.Itoa(value) {
t.Errorf("Failed to update %s annotation key: got=%s, want=%d", key, v, value) t.Errorf("Failed to update %s annotation key: got=%s, want=%d", key, v, value)
} }
} }
func checkAnnotationValue(t *testing.T, template *servingv1alpha1.RevisionTemplateSpec, key string, value string) {
anno := template.GetAnnotations()
if v, ok := anno[key]; !ok && v != value {
t.Errorf("Failed to update %s annotation key: got=%s, want=%s", key, v, value)
}
}
func checkContainerConcurrency(t *testing.T, template *servingv1alpha1.RevisionTemplateSpec, value *int64) { func checkContainerConcurrency(t *testing.T, template *servingv1alpha1.RevisionTemplateSpec, value *int64) {
if got, want := *template.Spec.ContainerConcurrency, *value; got != want { if got, want := *template.Spec.ContainerConcurrency, *value; got != want {
t.Errorf("Failed to update containerConcurrency value: got=%d, want=%d", got, want) t.Errorf("Failed to update containerConcurrency value: got=%d, want=%d", got, want)

View File

@ -67,6 +67,10 @@ func ConcurrencyTarget(m *metav1.ObjectMeta) *int {
return ret return ret
} }
func AutoscaleWindow(m *metav1.ObjectMeta) string {
return m.Annotations[autoscaling.WindowAnnotationKey]
}
func Port(revisionSpec *servingv1alpha1.RevisionSpec) *int32 { func Port(revisionSpec *servingv1alpha1.RevisionSpec) *int32 {
c, err := ContainerOfRevisionSpec(revisionSpec) c, err := ContainerOfRevisionSpec(revisionSpec)
if err != nil { if err != nil {

View File

@ -79,6 +79,14 @@ func TestServiceOptions(t *testing.T) {
test.validateServiceAnnotations(t, "svc3", map[string]string{"alpha": "direwolf", "brave": ""}) test.validateServiceAnnotations(t, "svc3", map[string]string{"alpha": "direwolf", "brave": ""})
test.serviceDelete(t, "svc3") test.serviceDelete(t, "svc3")
}) })
t.Run("create, update and validate service with autoscale window option", func(t *testing.T) {
test.serviceCreateWithOptions(t, "svc4", []string{"--autoscale-window", "1m"})
test.validateAutoscaleWindow(t, "svc4", "1m")
test.serviceUpdate(t, "svc4", []string{"--autoscale-window", "15s"})
test.validateAutoscaleWindow(t, "svc4", "15s")
test.serviceDelete(t, "svc4")
})
} }
func (test *e2eTest) serviceCreateWithOptions(t *testing.T, serviceName string, options []string) { func (test *e2eTest) serviceCreateWithOptions(t *testing.T, serviceName string, options []string) {
@ -121,6 +129,13 @@ func (test *e2eTest) validateServiceConcurrencyTarget(t *testing.T, serviceName,
} }
} }
func (test *e2eTest) validateAutoscaleWindow(t *testing.T, serviceName, window string) {
jsonpath := "jsonpath={.items[0].spec.template.metadata.annotations.autoscaling\\.knative\\.dev/window}"
out, err := test.kn.RunWithOpts([]string{"service", "list", serviceName, "-o", jsonpath}, runOpts{})
assert.NilError(t, err)
assert.Equal(t, out, window)
}
func (test *e2eTest) validateServiceMinScale(t *testing.T, serviceName, minScale string) { func (test *e2eTest) validateServiceMinScale(t *testing.T, 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/minScale}"
out, err := test.kn.RunWithOpts([]string{"service", "list", serviceName, "-o", jsonpath}, runOpts{}) out, err := test.kn.RunWithOpts([]string{"service", "list", serviceName, "-o", jsonpath}, runOpts{})