Skip to content

Commit

Permalink
Add support for command and args in service create (#635)
Browse files Browse the repository at this point in the history
* Add support for command and args in service create

* Add tests for new update functions
  • Loading branch information
dsimansk authored Feb 4, 2020
1 parent d82d557 commit ffdeafe
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
| Show envFrom when running describe service or revision
| https://github.com/knative/client/pull/630

| 🎁
| Add `--cmd` and `--arg` for customization of container entrypoint
| https://github.com/knative/client/pull/635[#635]

## v0.12.0 (2020-01-29)

[cols="1,10,3", options="header", width="100%"]
Expand Down
2 changes: 2 additions & 0 deletions docs/cmd/kn_service_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ kn service create NAME --image IMAGE [flags]

```
--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-).
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
--async Create service and don't wait for it to become ready.
--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)
--cmd string Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start or --cmd /app/start --arg myArg to pass aditional arguments.
--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. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
Expand Down
2 changes: 2 additions & 0 deletions docs/cmd/kn_service_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ kn service update NAME [flags]

```
--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-).
--arg stringArray Add argument to the container command. Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. You can use this flag multiple times.
--async Update service and don't wait for it to become ready.
--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)
--cmd string Specify command to be used as entrypoint instead of default one. Example: --cmd /app/start or --cmd /app/start --arg myArg to pass aditional arguments.
--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. To unset, specify the environment variable name followed by a "-" (e.g., NAME-).
Expand Down
27 changes: 27 additions & 0 deletions pkg/kn/commands/service/configuration_edit_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ type ConfigurationEditFlags struct {
Mount []string
Volume []string

Command string
Arg []string

RequestsFlags, LimitsFlags ResourceFlags
MinScale int
MaxScale int
Expand Down Expand Up @@ -102,6 +105,16 @@ func (p *ConfigurationEditFlags) addSharedFlags(command *cobra.Command) {
"To unset a ConfigMap/Secret reference, append \"-\" to the name, e.g. --volume myvolume-.")
p.markFlagMakesRevision("volume")

command.Flags().StringVarP(&p.Command, "cmd", "", "",
"Specify command to be used as entrypoint instead of default one. "+
"Example: --cmd /app/start or --cmd /app/start --arg myArg to pass aditional arguments.")
p.markFlagMakesRevision("cmd")
command.Flags().StringArrayVarP(&p.Arg, "arg", "", []string{},
"Add argument to the container command. "+
"Example: --arg myArg1 --arg --myArg2 --arg myArg3=3. "+
"You can use this flag multiple times.")
p.markFlagMakesRevision("arg")

command.Flags().StringVar(&p.RequestsFlags.CPU, "requests-cpu", "", "The requested CPU (e.g., 250m).")
p.markFlagMakesRevision("requests-cpu")
command.Flags().StringVar(&p.RequestsFlags.Memory, "requests-memory", "", "The requested memory (e.g., 64Mi).")
Expand Down Expand Up @@ -281,6 +294,20 @@ func (p *ConfigurationEditFlags) Apply(
return err
}

if cmd.Flags().Changed("cmd") {
err = servinglib.UpdateContainerCommand(template, p.Command)
if err != nil {
return err
}
}

if cmd.Flags().Changed("arg") {
err = servinglib.UpdateContainerArg(template, p.Arg)
if err != nil {
return err
}
}

if cmd.Flags().Changed("port") {
err = servinglib.UpdateContainerPort(template, p.Port)
if err != nil {
Expand Down
26 changes: 26 additions & 0 deletions pkg/kn/commands/service/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"strings"
"testing"

"gotest.tools/assert"

api_errors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
Expand Down Expand Up @@ -156,6 +158,30 @@ func TestServiceCreateImageSync(t *testing.T) {
}
}

func TestServiceCreateCommand(t *testing.T) {
action, created, _, err := fakeServiceCreate([]string{
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz", "--cmd", "/app/start", "--async"}, false, false)
assert.NilError(t, err)
assert.Assert(t, action.Matches("create", "services"))

template, err := servinglib.RevisionTemplateOfService(created)
assert.NilError(t, err)
assert.DeepEqual(t, template.Spec.Containers[0].Command, []string{"/app/start"})
}

func TestServiceCreateArg(t *testing.T) {
action, created, _, err := fakeServiceCreate([]string{
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz", "--arg", "myArg1", "--arg", "--myArg2", "--arg", "--myArg3=3", "--async"}, false, false)
assert.NilError(t, err)
assert.Assert(t, action.Matches("create", "services"))

expectedArg := []string{"myArg1", "--myArg2", "--myArg3=3"}

template, err := servinglib.RevisionTemplateOfService(created)
assert.NilError(t, err)
assert.DeepEqual(t, template.Spec.Containers[0].Args, expectedArg)
}

func TestServiceCreateEnv(t *testing.T) {
action, created, _, err := fakeServiceCreate([]string{
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz", "-e", "A=DOGS", "--env", "B=WOLVES", "--env=EMPTY", "--async"}, false, false)
Expand Down
38 changes: 38 additions & 0 deletions pkg/kn/commands/service/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,44 @@ func TestServiceUpdateImage(t *testing.T) {
}
}

func TestServiceUpdateCommand(t *testing.T) {
orig := newEmptyService()

origTemplate, err := servinglib.RevisionTemplateOfService(orig)
assert.NilError(t, err)

err = servinglib.UpdateContainerCommand(origTemplate, "./start")
assert.NilError(t, err)

action, updated, _, err := fakeServiceUpdate(orig, []string{
"service", "update", "foo", "--cmd", "/app/start", "--async"}, false)
assert.NilError(t, err)
assert.Assert(t, action.Matches("update", "services"))

updatedTemplate, err := servinglib.RevisionTemplateOfService(updated)
assert.NilError(t, err)
assert.DeepEqual(t, updatedTemplate.Spec.Containers[0].Command, []string{"/app/start"})
}

func TestServiceUpdateArg(t *testing.T) {
orig := newEmptyService()

origTemplate, err := servinglib.RevisionTemplateOfService(orig)
assert.NilError(t, err)

err = servinglib.UpdateContainerArg(origTemplate, []string{"myArg0"})
assert.NilError(t, err)

action, updated, _, err := fakeServiceUpdate(orig, []string{
"service", "update", "foo", "--arg", "myArg1", "--arg", "--myArg2", "--arg", "--myArg3=3", "--async"}, false)
assert.NilError(t, err)
assert.Assert(t, action.Matches("update", "services"))

updatedTemplate, err := servinglib.RevisionTemplateOfService(updated)
assert.NilError(t, err)
assert.DeepEqual(t, updatedTemplate.Spec.Containers[0].Args, []string{"myArg1", "--myArg2", "--myArg3=3"})
}

func TestServiceUpdateRevisionNameExplicit(t *testing.T) {
orig := newEmptyServiceBetaAPIStyle()

Expand Down
20 changes: 20 additions & 0 deletions pkg/serving/config_changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,26 @@ func FreezeImageToDigest(template *servingv1alpha1.RevisionTemplateSpec, baseRev
return nil
}

// UpdateContainerCommand updates container with a given argument
func UpdateContainerCommand(template *servingv1alpha1.RevisionTemplateSpec, command string) error {
container, err := ContainerOfRevisionTemplate(template)
if err != nil {
return err
}
container.Command = []string{command}
return nil
}

// UpdateContainerArg updates container with a given argument
func UpdateContainerArg(template *servingv1alpha1.RevisionTemplateSpec, arg []string) error {
container, err := ContainerOfRevisionTemplate(template)
if err != nil {
return err
}
container.Args = arg
return nil
}

// UpdateContainerPort updates container with a give port
func UpdateContainerPort(template *servingv1alpha1.RevisionTemplateSpec, port int32) error {
container, err := ContainerOfRevisionTemplate(template)
Expand Down
22 changes: 22 additions & 0 deletions pkg/serving/config_changes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,28 @@ func checkContainerImage(t *testing.T, template *servingv1alpha1.RevisionTemplat
}
}

func TestUpdateContainerCommand(t *testing.T) {
template, _ := getV1alpha1RevisionTemplateWithOldFields()
err := UpdateContainerCommand(template, "/app/start")
assert.NilError(t, err)
assert.DeepEqual(t, template.Spec.GetContainer().Command, []string{"/app/start"})

err = UpdateContainerCommand(template, "/app/latest")
assert.NilError(t, err)
assert.DeepEqual(t, template.Spec.GetContainer().Command, []string{"/app/latest"})
}

func TestUpdateContainerArg(t *testing.T) {
template, _ := getV1alpha1RevisionTemplateWithOldFields()
err := UpdateContainerArg(template, []string{"--myArg"})
assert.NilError(t, err)
assert.DeepEqual(t, template.Spec.GetContainer().Args, []string{"--myArg"})

err = UpdateContainerArg(template, []string{"myArg1", "--myArg2"})
assert.NilError(t, err)
assert.DeepEqual(t, template.Spec.GetContainer().Args, []string{"myArg1", "--myArg2"})
}

func TestUpdateContainerPort(t *testing.T) {
template, _ := getV1alpha1Config()
err := UpdateContainerPort(template, 8888)
Expand Down

0 comments on commit ffdeafe

Please sign in to comment.