mirror of https://github.com/knative/client.git
Add support for command and args in service create (#635)
* Add support for command and args in service create * Add tests for new update functions
This commit is contained in:
parent
d82d55731c
commit
ffdeafe33e
|
|
@ -24,6 +24,10 @@
|
||||||
| Show envFrom when running describe service or revision
|
| Show envFrom when running describe service or revision
|
||||||
| https://github.com/knative/client/pull/630
|
| 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)
|
## v0.12.0 (2020-01-29)
|
||||||
|
|
||||||
[cols="1,10,3", options="header", width="100%"]
|
[cols="1,10,3", options="header", width="100%"]
|
||||||
|
|
|
||||||
|
|
@ -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-).
|
--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.
|
--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)
|
--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-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.
|
--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-).
|
-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-).
|
||||||
|
|
|
||||||
|
|
@ -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-).
|
--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.
|
--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)
|
--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-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.
|
--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-).
|
-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-).
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,9 @@ type ConfigurationEditFlags struct {
|
||||||
Mount []string
|
Mount []string
|
||||||
Volume []string
|
Volume []string
|
||||||
|
|
||||||
|
Command string
|
||||||
|
Arg []string
|
||||||
|
|
||||||
RequestsFlags, LimitsFlags ResourceFlags
|
RequestsFlags, LimitsFlags ResourceFlags
|
||||||
MinScale int
|
MinScale int
|
||||||
MaxScale int
|
MaxScale int
|
||||||
|
|
@ -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-.")
|
"To unset a ConfigMap/Secret reference, append \"-\" to the name, e.g. --volume myvolume-.")
|
||||||
p.markFlagMakesRevision("volume")
|
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).")
|
command.Flags().StringVar(&p.RequestsFlags.CPU, "requests-cpu", "", "The requested CPU (e.g., 250m).")
|
||||||
p.markFlagMakesRevision("requests-cpu")
|
p.markFlagMakesRevision("requests-cpu")
|
||||||
command.Flags().StringVar(&p.RequestsFlags.Memory, "requests-memory", "", "The requested memory (e.g., 64Mi).")
|
command.Flags().StringVar(&p.RequestsFlags.Memory, "requests-memory", "", "The requested memory (e.g., 64Mi).")
|
||||||
|
|
@ -281,6 +294,20 @@ func (p *ConfigurationEditFlags) Apply(
|
||||||
return err
|
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") {
|
if cmd.Flags().Changed("port") {
|
||||||
err = servinglib.UpdateContainerPort(template, p.Port)
|
err = servinglib.UpdateContainerPort(template, p.Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"gotest.tools/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"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
|
@ -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) {
|
func TestServiceCreateEnv(t *testing.T) {
|
||||||
action, created, _, err := fakeServiceCreate([]string{
|
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)
|
"service", "create", "foo", "--image", "gcr.io/foo/bar:baz", "-e", "A=DOGS", "--env", "B=WOLVES", "--env=EMPTY", "--async"}, false, false)
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
func TestServiceUpdateRevisionNameExplicit(t *testing.T) {
|
||||||
orig := newEmptyServiceBetaAPIStyle()
|
orig := newEmptyServiceBetaAPIStyle()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,26 @@ func FreezeImageToDigest(template *servingv1alpha1.RevisionTemplateSpec, baseRev
|
||||||
return nil
|
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
|
// UpdateContainerPort updates container with a give port
|
||||||
func UpdateContainerPort(template *servingv1alpha1.RevisionTemplateSpec, port int32) error {
|
func UpdateContainerPort(template *servingv1alpha1.RevisionTemplateSpec, port int32) error {
|
||||||
container, err := ContainerOfRevisionTemplate(template)
|
container, err := ContainerOfRevisionTemplate(template)
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
func TestUpdateContainerPort(t *testing.T) {
|
||||||
template, _ := getV1alpha1Config()
|
template, _ := getV1alpha1Config()
|
||||||
err := UpdateContainerPort(template, 8888)
|
err := UpdateContainerPort(template, 8888)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue