Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/cmd/kn_service_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ kn service create NAME --image IMAGE [flags]
### Options

```
--concurrency-limit int Hard Limit of concurrent requests to be processed by a single replica.
--concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables.
--force Create service forcefully, replaces existing service if any.
-h, --help help for create
--image string Image to run.
--limits-cpu string The limits on the requested CPU (e.g., 1000m).
--limits-memory string The limits on the requested CPU (e.g., 1024Mi).
--max-scale int Maximal number of replicas.
--min-scale int Minimal number of replicas.
-n, --namespace string List the requested object(s) in given namespace.
--requests-cpu string The requested CPU (e.g., 250m).
--requests-memory string The requested CPU (e.g., 64Mi).
Expand Down
4 changes: 4 additions & 0 deletions docs/cmd/kn_service_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ kn service update NAME [flags]
### Options

```
--concurrency-limit int Hard Limit of concurrent requests to be processed by a single replica.
--concurrency-target int Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.
-e, --env stringArray Environment variable to set. NAME=value; you may provide this flag any number of times to set multiple environment variables.
-h, --help help for update
--image string Image to run.
--limits-cpu string The limits on the requested CPU (e.g., 1000m).
--limits-memory string The limits on the requested CPU (e.g., 1024Mi).
--max-scale int Maximal number of replicas.
--min-scale int Minimal number of replicas.
-n, --namespace string List the requested object(s) in given namespace.
--requests-cpu string The requested CPU (e.g., 250m).
--requests-memory string The requested CPU (e.g., 64Mi).
Expand Down
11 changes: 11 additions & 0 deletions pkg/kn/commands/service/configuration_edit_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ type ConfigurationEditFlags struct {
Env []string
RequestsFlags, LimitsFlags ResourceFlags
ForceCreate bool
MinScale int
MaxScale int
ConcurrencyTarget int
ConcurrencyLimit int
}

type ResourceFlags struct {
Expand All @@ -46,6 +50,10 @@ func (p *ConfigurationEditFlags) AddUpdateFlags(command *cobra.Command) {
command.Flags().StringVar(&p.RequestsFlags.Memory, "requests-memory", "", "The requested CPU (e.g., 64Mi).")
command.Flags().StringVar(&p.LimitsFlags.CPU, "limits-cpu", "", "The limits on the requested CPU (e.g., 1000m).")
command.Flags().StringVar(&p.LimitsFlags.Memory, "limits-memory", "", "The limits on the requested CPU (e.g., 1024Mi).")
command.Flags().IntVar(&p.MinScale, "min-scale", 0, "Minimal number of replicas.")
command.Flags().IntVar(&p.MaxScale, "max-scale", 0, "Maximal number of replicas.")
command.Flags().IntVar(&p.ConcurrencyTarget, "concurrency-target", 0, "Recommendation for when to scale up based on the concurrent number of incoming request. Defaults to --concurrency-limit when given.")
command.Flags().IntVar(&p.ConcurrencyLimit, "concurrency-limit", 0, "Hard Limit of concurrent requests to be processed by a single replica.")
}

func (p *ConfigurationEditFlags) AddCreateFlags(command *cobra.Command) {
Expand Down Expand Up @@ -93,6 +101,9 @@ func (p *ConfigurationEditFlags) Apply(service *servingv1alpha1.Service, cmd *co
if err != nil {
return err
}

servinglib.UpdateConcurrencyConfiguration(template, p.MinScale, p.MaxScale, p.ConcurrencyTarget, p.ConcurrencyLimit)

return nil
}

Expand Down
36 changes: 36 additions & 0 deletions pkg/kn/commands/service/service_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,42 @@ func TestServiceCreateRequestsLimitsMemory(t *testing.T) {
}
}

func TestServiceCreateMaxMinScale(t *testing.T) {
action, created, _, err := fakeServiceCreate([]string{
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz",
"--min-scale", "1", "--max-scale", "5", "--concurrency-target", "10", "--concurrency-limit", "100"})

if err != nil {
t.Fatal(err)
} else if !action.Matches("create", "services") {
t.Fatalf("Bad action %v", action)
}

template, err := servinglib.GetRevisionTemplate(created)
if err != nil {
t.Fatal(err)
}

actualAnnos := template.Annotations
expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1",
"autoscaling.knative.dev/maxScale", "5",
"autoscaling.knative.dev/target", "10",
}

for i := 0; i < len(expectedAnnos); i += 2 {
anno := expectedAnnos[i]
if actualAnnos[anno] != expectedAnnos[i+1] {
t.Fatalf("Unexpected annotation value for %s : %s (actual) != %s (expected)",
anno, actualAnnos[anno], expectedAnnos[i+1])
}
}

if template.Spec.ContainerConcurrency != 100 {
t.Fatalf("container concurrency not set to given value 1000")
}
}

func TestServiceCreateRequestsLimitsCPUMemory(t *testing.T) {
action, created, _, err := fakeServiceCreate([]string{
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz",
Expand Down
85 changes: 64 additions & 21 deletions pkg/kn/commands/service/service_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,27 +64,7 @@ func fakeServiceUpdate(original *v1alpha1.Service, args []string) (
}

func TestServiceUpdateImage(t *testing.T) {
orig := &v1alpha1.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
APIVersion: "knative.dev/v1alpha1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
},
Spec: v1alpha1.ServiceSpec{
DeprecatedRunLatest: &v1alpha1.RunLatestType{
Configuration: v1alpha1.ConfigurationSpec{
DeprecatedRevisionTemplate: &v1alpha1.RevisionTemplateSpec{
Spec: v1alpha1.RevisionSpec{
DeprecatedContainer: &corev1.Container{},
},
},
},
},
},
}
orig := newEmptyService()

template, err := servinglib.GetRevisionTemplate(orig)
if err != nil {
Expand All @@ -110,6 +90,45 @@ func TestServiceUpdateImage(t *testing.T) {
}
}

func TestServiceUpdateMaxMinScale(t *testing.T) {
original := newEmptyService()

action, updated, _, err := fakeServiceUpdate(original, []string{
"service", "update", "foo",
"--min-scale", "1", "--max-scale", "5", "--concurrency-target", "10", "--concurrency-limit", "100"})

if err != nil {
t.Fatal(err)
} else if !action.Matches("update", "services") {
t.Fatalf("Bad action %v", action)
}

template, err := servinglib.GetRevisionTemplate(updated)
if err != nil {
t.Fatal(err)
}

actualAnnos := template.Annotations
expectedAnnos := []string{
"autoscaling.knative.dev/minScale", "1",
"autoscaling.knative.dev/maxScale", "5",
"autoscaling.knative.dev/target", "10",
}

for i := 0; i < len(expectedAnnos); i += 2 {
anno := expectedAnnos[i]
if actualAnnos[anno] != expectedAnnos[i+1] {
t.Fatalf("Unexpected annotation value for %s : %s (actual) != %s (expected)",
anno, actualAnnos[anno], expectedAnnos[i+1])
}
}

if template.Spec.ContainerConcurrency != 100 {
t.Fatalf("container concurrency not set to given value 1000")
}

}

func TestServiceUpdateEnv(t *testing.T) {
orig := &v1alpha1.Service{
TypeMeta: metav1.TypeMeta{
Expand Down Expand Up @@ -279,6 +298,30 @@ func TestServiceUpdateRequestsLimitsCPU_and_Memory(t *testing.T) {
}
}

func newEmptyService() *v1alpha1.Service {
return &v1alpha1.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
APIVersion: "knative.dev/v1alpha1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
},
Spec: v1alpha1.ServiceSpec{
DeprecatedRunLatest: &v1alpha1.RunLatestType{
Configuration: v1alpha1.ConfigurationSpec{
DeprecatedRevisionTemplate: &v1alpha1.RevisionTemplateSpec{
Spec: v1alpha1.RevisionSpec{
DeprecatedContainer: &corev1.Container{},
},
},
},
},
},
}
}

func createMockServiceWithResources(t *testing.T, requestCPU, requestMemory, limitsCPU, limitsMemory string) *v1alpha1.Service {
service := &v1alpha1.Service{
TypeMeta: metav1.TypeMeta{
Expand Down
29 changes: 29 additions & 0 deletions pkg/serving/config_changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ package serving

import (
"fmt"
"strconv"

servingv1alpha1 "github.com/knative/serving/pkg/apis/serving/v1alpha1"
servingv1beta1 "github.com/knative/serving/pkg/apis/serving/v1beta1"
corev1 "k8s.io/api/core/v1"
)

Expand All @@ -33,6 +35,33 @@ func UpdateEnvVars(template *servingv1alpha1.RevisionTemplateSpec, vars map[stri
return nil
}

// Update min and max scale annotation if larger than 0
func UpdateConcurrencyConfiguration(template *servingv1alpha1.RevisionTemplateSpec, minScale int, maxScale int, target int, limit int) {
if minScale != 0 {
UpdateAnnotation(template, "autoscaling.knative.dev/minScale", strconv.Itoa(minScale))
}
if maxScale != 0 {
UpdateAnnotation(template, "autoscaling.knative.dev/maxScale", strconv.Itoa(maxScale))
}
if target != 0 {
UpdateAnnotation(template, "autoscaling.knative.dev/target", strconv.Itoa(target))
}

if limit != 0 {
template.Spec.ContainerConcurrency = servingv1beta1.RevisionContainerConcurrencyType(limit)
}
}

// Updater (or add) an annotation to the given service
func UpdateAnnotation(template *servingv1alpha1.RevisionTemplateSpec, annotation string, value string) {
annoMap := template.Annotations
if annoMap == nil {
annoMap = make(map[string]string)
template.Annotations = annoMap
}
annoMap[annotation] = value
}

// Utility function to translate between the API list form of env vars, and the
// more convenient map form.
func EnvToMap(vars []corev1.EnvVar) (map[string]string, error) {
Expand Down
18 changes: 18 additions & 0 deletions pkg/serving/config_changes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ import (
corev1 "k8s.io/api/core/v1"
)

func TestUpdateAutoscalingAnnotations(t *testing.T) {
template := &servingv1alpha1.RevisionTemplateSpec{}
UpdateConcurrencyConfiguration(template, 10, 100, 1000, 1000)
annos := template.Annotations
if annos["autoscaling.knative.dev/minScale"] != "10" {
t.Error("minScale failed")
}
if annos["autoscaling.knative.dev/maxScale"] != "100" {
t.Error("maxScale failed")
}
if annos["autoscaling.knative.dev/target"] != "1000" {
t.Error("target failed")
}
if template.Spec.ContainerConcurrency != 1000 {
t.Error("limit failed")
}
}

func TestUpdateEnvVarsNew(t *testing.T) {
template, container := getV1alpha1RevisionTemplateWithOldFields()
testUpdateEnvVarsNew(t, template, container)
Expand Down
4 changes: 2 additions & 2 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ github.com/knative/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1
github.com/knative/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1/fake
github.com/knative/serving/pkg/apis/serving
github.com/knative/serving/pkg/apis/serving/v1alpha1
github.com/knative/serving/pkg/apis/serving/v1beta1
github.com/knative/serving/pkg/client/clientset/versioned/scheme
github.com/knative/serving/pkg/apis/autoscaling
github.com/knative/serving/pkg/apis/networking
github.com/knative/serving/pkg/apis/networking/v1alpha1
github.com/knative/serving/pkg/apis/serving/v1beta1
github.com/knative/serving/pkg/apis/autoscaling/v1alpha1
github.com/knative/serving/pkg/apis/config
github.com/knative/serving/pkg/apis/autoscaling/v1alpha1
# github.com/knative/test-infra v0.0.0-20190531180034-a3c073a2fea1
github.com/knative/test-infra/scripts
# github.com/magiconair/properties v1.8.0
Expand Down