Repository: knative/client (go)

Issue:
Add support to allow scaling metric type (concurrency, rps, cpu, memory)
<!-- If you need to report a security issue with Knative, send an email to knative-security@googlegroups.com. -->

### Feature request
Currently,  I can't set the autoscaler metric with rps.    How about add a new option `--autoscaler-metric` ?
### Use case

Currently, I can't achieve below knative creation with `kn`
```
cat <<EOF | kubectl apply -n default -f -
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: ceperftesthttp-rps
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/metric: rps
        autoscaling.knative.dev/target: "100"
        autoscaling.knative.dev/minScale: "3"
        autoscaling.knative.dev/maxScale: "50"        
    spec:
      containerConcurrency: 100
      containers:
        - image: .....
EOF
```

### UI Example

how about using 
`kn service create --autoscaler-metric rps` for above?  The default value for `--autoscaler-metric` should be `concurrency`

Pull request description:
Added subpath functionality to --mount flag
## Description
User can now specify subpath of a volume to be mounted using the `--mount` flag
<!-- Please add a short summary about what the pull request is going to bring on the table -->

```
gvyas-mac:client gvyas$ ./kn service update hello-example-2 --image gcr.io/knative-samples/helloworld-go --mount /mydir2=cm:cm1/xyzzz/jhg --mount /etc/mydir3=sc:my-sec
Updating Service 'hello-example-2' in namespace 'default':

  0.053s The Configuration is still working to reflect the latest desired specification.
  4.387s Traffic is not yet migrated to the latest revision.
  4.428s Ingress has not yet been reconciled.
  4.488s Waiting for load balancer to be ready
  4.659s Ready to serve.

Service 'hello-example-2' updated to latest revision 'hello-example-2-00005' is available at URL:
http://hello-example-2.default.10.111.180.117.sslip.io
```
```
gvyas-mac:client gvyas$ kubectl get pod hello-example-2-00005-deployment-746c9959-dwtbh -o json | jq -r '.spec.containers[0].volumeMounts'
[
  {
    "mountPath": "/mydir",
    "name": "myvol",
    "readOnly": true,
    "subPath": "abc/xyz"
  },
  {
    "mountPath": "/mydir2",
    "name": "mydir2-e1669d63",
    "readOnly": true,
    "subPath": "xyzzz/jhg"
  },
  {
    "mountPath": "/etc/mydir3",
    "name": "etc-mydir3-cc5ae7ae",
    "readOnly": true
  },
  {
    "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
    "name": "kube-api-access-t9kks",
    "readOnly": true
  }
]

```

## Changes

<!-- Please add list of more detailed changes. These changes should be reflected also in the commit messages -->

* Modified `--mount` flag so it can process subpaths in volumes
* Added unit tests


## Reference

<!-- Please add the corresponding issue number which this pull request is about to fix -->
Fixes #1205

<!--
Please add an entry to CHANGELOG.adoc file, too, as part of your Pull Request.

In the following cases, add a short description of PR to the unreleased section in CHANGELOG.adoc:

- 🎁 New feature
- 🐛 Bug fix
- ✨ Feature Update
- 🐣 Refactoring
- 🗑️ Remove feature or internal logic

See other entries in CHANGELOG.adoc as an example for how to add the entry, including a reference to the corresponding issue/PR

PLEASE DON'T ADD THAT LINE HERE IN THE PULL-REQUEST DESCRIPTION BUT DIRECTLY IN CHANGELOG.ADOC AND ADD CHANGELOG.ADOC AS PART OF YOUR PULL-REQUEST.
-->

<!--
To automatically lint go code in this pull request uncomment the line below. You get feedback as comments on your pull request then -->

<!--
/lint
-->


Patch:
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index ec3cf426..6a5c6724 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -32,6 +32,10 @@
 | Added --scale-metric flag to configure metric name
 | https://github.com/knative/client/pull/1653[#1653]
 
+| 🎁
+| Added subpath functionality to --mount flag
+| https://github.com/knative/client/pull/1655[#1655]
+
 |===
 ## v1.3.0 (2022-03-08)
 [cols="1,10,3", options="header", width="100%"]
diff --git a/docs/cmd/kn_container_add.md b/docs/cmd/kn_container_add.md
index 01d5146e..be61871c 100644
--- a/docs/cmd/kn_container_add.md
+++ b/docs/cmd/kn_container_add.md
@@ -38,7 +38,7 @@ kn container add NAME
   -h, --help                         help for add
       --image string                 Image to run.
       --limit strings                The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
-      --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.
+      --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 specify a volume subpath by following the volume name with slash separated path. Example: --mount /mydir=cm:myconfigmap/subpath/to/be/mounted. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
   -p, --port string                  The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
       --pull-policy string           Image pull policy. Valid values (case insensitive): Always | Never | IfNotPresent
       --pull-secret string           Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace.
diff --git a/docs/cmd/kn_service_apply.md b/docs/cmd/kn_service_apply.md
index 35c7234c..73a222d2 100644
--- a/docs/cmd/kn_service_apply.md
+++ b/docs/cmd/kn_service_apply.md
@@ -50,7 +50,7 @@ kn service apply s0 --filename my-svc.yml
       --label-service 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-). This flag takes precedence over the "label" flag.
       --limit strings                     The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
       --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)
-      --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.
+      --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 specify a volume subpath by following the volume name with slash separated path. Example: --mount /mydir=cm:myconfigmap/subpath/to/be/mounted. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
   -n, --namespace string                  Specify the namespace to operate in.
       --no-cluster-local                  Do not specify that the service be private. (--no-cluster-local will make the service publicly available) (default true)
       --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)
diff --git a/docs/cmd/kn_service_create.md b/docs/cmd/kn_service_create.md
index d522c335..5dce7e29 100644
--- a/docs/cmd/kn_service_create.md
+++ b/docs/cmd/kn_service_create.md
@@ -75,7 +75,7 @@ kn service create NAME --image IMAGE
       --label-service 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-). This flag takes precedence over the "label" flag.
       --limit strings                     The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
       --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)
-      --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.
+      --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 specify a volume subpath by following the volume name with slash separated path. Example: --mount /mydir=cm:myconfigmap/subpath/to/be/mounted. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
   -n, --namespace string                  Specify the namespace to operate in.
       --no-cluster-local                  Do not specify that the service be private. (--no-cluster-local will make the service publicly available) (default true)
       --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)
diff --git a/docs/cmd/kn_service_update.md b/docs/cmd/kn_service_update.md
index 86f46fcc..cc747559 100644
--- a/docs/cmd/kn_service_update.md
+++ b/docs/cmd/kn_service_update.md
@@ -62,7 +62,7 @@ kn service update NAME
       --label-service 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-). This flag takes precedence over the "label" flag.
       --limit strings                     The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
       --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)
-      --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.
+      --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 specify a volume subpath by following the volume name with slash separated path. Example: --mount /mydir=cm:myconfigmap/subpath/to/be/mounted. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
   -n, --namespace string                  Specify the namespace to operate in.
       --no-cluster-local                  Do not specify that the service be private. (--no-cluster-local will make the service publicly available) (default true)
       --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)
diff --git a/docs/cmd/kn_source_container_create.md b/docs/cmd/kn_source_container_create.md
index 93dd0695..fdaa3658 100644
--- a/docs/cmd/kn_source_container_create.md
+++ b/docs/cmd/kn_source_container_create.md
@@ -27,7 +27,7 @@ kn source container create NAME --image IMAGE --sink SINK
   -h, --help                         help for create
       --image string                 Image to run.
       --limit strings                The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
-      --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.
+      --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 specify a volume subpath by following the volume name with slash separated path. Example: --mount /mydir=cm:myconfigmap/subpath/to/be/mounted. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
   -n, --namespace string             Specify the namespace to operate in.
   -p, --port string                  The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
       --pull-policy string           Image pull policy. Valid values (case insensitive): Always | Never | IfNotPresent
diff --git a/docs/cmd/kn_source_container_update.md b/docs/cmd/kn_source_container_update.md
index 95d96ef8..322e605a 100644
--- a/docs/cmd/kn_source_container_update.md
+++ b/docs/cmd/kn_source_container_update.md
@@ -27,7 +27,7 @@ kn source container update NAME --image IMAGE
   -h, --help                         help for update
       --image string                 Image to run.
       --limit strings                The resource requirement limits for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource limit, append "-" to the resource name, e.g. '--limit memory-'.
-      --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.
+      --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 specify a volume subpath by following the volume name with slash separated path. Example: --mount /mydir=cm:myconfigmap/subpath/to/be/mounted. You can use this flag multiple times. For unmounting a directory, append "-", e.g. --mount /mydir-, which also removes any auto-generated volume.
   -n, --namespace string             Specify the namespace to operate in.
   -p, --port string                  The port where application listens on, in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'.
       --pull-policy string           Image pull policy. Valid values (case insensitive): Always | Never | IfNotPresent
diff --git a/go.mod b/go.mod
index a2a23c8e..128d2922 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.17
 require (
 	github.com/emicklei/go-restful v2.15.0+incompatible // indirect
 	github.com/google/go-cmp v0.5.7
-	github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e // indirect
+	github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387 // indirect
 	github.com/hashicorp/golang-lru v0.5.4
 	github.com/hashicorp/hcl v1.0.0
 	github.com/mitchellh/go-homedir v1.1.0
@@ -22,11 +22,11 @@ require (
 	k8s.io/cli-runtime v0.23.4
 	k8s.io/client-go v0.23.5
 	k8s.io/code-generator v0.23.5
-	knative.dev/eventing v0.30.1-0.20220413070808-1b90ef335226
+	knative.dev/eventing v0.30.1-0.20220415141711-ff55a456c3f9
 	knative.dev/hack v0.0.0-20220411131823-6ffd8417de7c
 	knative.dev/networking v0.0.0-20220412163509-1145ec58c8be
 	knative.dev/pkg v0.0.0-20220412134708-e325df66cb51
-	knative.dev/serving v0.30.1-0.20220413003907-2de1474b55ba
+	knative.dev/serving v0.30.1-0.20220416140111-2e5ca679a71e
 	sigs.k8s.io/yaml v1.3.0
 )
 
@@ -121,7 +121,7 @@ require (
 	gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
 	google.golang.org/api v0.70.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf // indirect
+	google.golang.org/genproto v0.0.0-20220301145929-1ac2ace0dbf7 // indirect
 	google.golang.org/grpc v1.44.0 // indirect
 	google.golang.org/protobuf v1.27.1 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
diff --git a/go.sum b/go.sum
index eea144d3..47c2a95b 100644
--- a/go.sum
+++ b/go.sum
@@ -663,6 +663,8 @@ github.com/google/go-containerregistry v0.8.0/go.mod h1:wW5v71NHGnQyb4k+gSshjxid
 github.com/google/go-containerregistry v0.8.1-0.20220110151055-a61fd0a8e2bb/go.mod h1:wW5v71NHGnQyb4k+gSshjxidrC7lN33MdWEn+Mz9TsI=
 github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e h1:1KGep3inUBSyCDbpk4noN5CfemOpEpQPPnN7UbBrdCU=
 github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e/go.mod h1:MMbnwuvLeZJRPqhTs8jDWc8xGlOs5YCGx1TSc/qdExk=
+github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387 h1:GWICy4b02s8EA1M9H5krRQ48BKpIHO5LtBBm2BQLhx0=
+github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387/go.mod h1:eTLvLZaEe2FoQsb25t7BLxQQryyrwHTzFfwxN87mhAw=
 github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20220328141311-efc62d802606/go.mod h1:gm/Zjh0iiPBfwgDIYgHJCRxaGzBZu1njCgwX1EmC1Tw=
 github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20220301182634-bfe2ffc6b6bd/go.mod h1:MO/Ilc3XTxy/Pi8aMXEiRUl6icOqResFyhSFCLlqtR8=
 github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
@@ -1178,6 +1180,7 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
 github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
 github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA=
+github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
 github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
@@ -1999,6 +2002,8 @@ google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ6
 google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf h1:SVYXkUz2yZS9FWb2Gm8ivSlbNQzL2Z/NpPKE3RG2jWk=
 google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
+google.golang.org/genproto v0.0.0-20220301145929-1ac2ace0dbf7 h1:6fWaU2vz6/23eNdMU1V00ZPO5AZFQ2SLsO6r/z0Z2H0=
+google.golang.org/genproto v0.0.0-20220301145929-1ac2ace0dbf7/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
 google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -2184,6 +2189,8 @@ k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/
 knative.dev/caching v0.0.0-20220412015107-318083f279be/go.mod h1:FqsgCB99NLJq1c8ZtpHYAb/3Oalgko9i4nF45IiKPio=
 knative.dev/eventing v0.30.1-0.20220413070808-1b90ef335226 h1:InSxj41bc1REMpsz9YR8IwxgO5KpjosBgd1Pwtzwf5k=
 knative.dev/eventing v0.30.1-0.20220413070808-1b90ef335226/go.mod h1:C1vLgthI00ev8zSqToU/sVgI6LI0ZQgezs0GX9uZ8l8=
+knative.dev/eventing v0.30.1-0.20220415141711-ff55a456c3f9 h1:Cf5i43bXtjFTvq12JtItR3dyhlhOgTVXQ31o2lFxViM=
+knative.dev/eventing v0.30.1-0.20220415141711-ff55a456c3f9/go.mod h1:Ld/pcIDX2nr7MvBOruoFFonzzDdpGbKsWDOYvpRoofo=
 knative.dev/hack v0.0.0-20220328133751-f06773764ce3/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
 knative.dev/hack v0.0.0-20220411131823-6ffd8417de7c h1:aXsFXeky/GccNQxwf72CS4NR3EoqTqsCVNKQnblfwr0=
 knative.dev/hack v0.0.0-20220411131823-6ffd8417de7c/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
@@ -2196,8 +2203,11 @@ knative.dev/pkg v0.0.0-20220411234407-00c122e376d0/go.mod h1:0A5D5tOLettuVoi5x+0
 knative.dev/pkg v0.0.0-20220412134708-e325df66cb51 h1:4AmaxeY7+r/PYYz3HS9pMY21Mw3ykO6STLFEk2FoJ2s=
 knative.dev/pkg v0.0.0-20220412134708-e325df66cb51/go.mod h1:j2MeD8s+JoCu1vegX80GbRXV/xd20Jm1NznxBYtVXiM=
 knative.dev/reconciler-test v0.0.0-20220411142808-55eab02440e9/go.mod h1:gH/ghOMDp7c2I2EAAhH4kYh0MI2hJ75OtiAMfeSl85o=
+knative.dev/reconciler-test v0.0.0-20220412141310-6da8e62f926f/go.mod h1:/25SELzYrVr+e+nARQh88d43BdHSP0JBfwUe3x/88OE=
 knative.dev/serving v0.30.1-0.20220413003907-2de1474b55ba h1:2v3VApF5OipZ58egt6GHS8YY4R5UwUuIH+y40PyUfbo=
 knative.dev/serving v0.30.1-0.20220413003907-2de1474b55ba/go.mod h1:b+wL9MBshkUyn8q7SCo+swF6qfrsaWG7cDa/AWuI4Nw=
+knative.dev/serving v0.30.1-0.20220416140111-2e5ca679a71e h1:iYq+sfkyQDQ0rfkbWPNF5j29geGXSMW4u/NV19EDedY=
+knative.dev/serving v0.30.1-0.20220416140111-2e5ca679a71e/go.mod h1:+U3xtXJ3iUt78ROr5CKc4OtTERCQtW2CizZ/fXFqp18=
 mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48=
 mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
 mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
diff --git a/pkg/kn/flags/podspec.go b/pkg/kn/flags/podspec.go
index ccd0b1eb..f79efab0 100644
--- a/pkg/kn/flags/podspec.go
+++ b/pkg/kn/flags/podspec.go
@@ -140,6 +140,8 @@ func (p *PodSpecFlags) AddFlags(flagset *pflag.FlagSet) []string {
 		"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 specify a volume subpath by following the volume name with slash separated path. "+
+			"Example: --mount /mydir=cm:myconfigmap/subpath/to/be/mounted. "+
 			"You can use this flag multiple times. "+
 			"For unmounting a directory, append \"-\", e.g. --mount /mydir-, which also removes any auto-generated volume.")
 	flagNames = append(flagNames, "mount")
diff --git a/pkg/kn/flags/podspec_helper.go b/pkg/kn/flags/podspec_helper.go
index f6ff0dfa..e4582404 100644
--- a/pkg/kn/flags/podspec_helper.go
+++ b/pkg/kn/flags/podspec_helper.go
@@ -38,6 +38,11 @@ const (
 	PortFormatErr = "the port specification '%s' is not valid. Please provide in the format 'NAME:PORT', where 'NAME' is optional. Examples: '--port h2c:8080' , '--port 8080'."
 )
 
+type MountInfo struct {
+	VolumeName string
+	SubPath    string
+}
+
 func (vt VolumeSourceType) String() string {
 	names := [...]string{"config-map", "secret"}
 	if vt < ConfigMapVolumeSourceType || vt > SecretVolumeSourceType {
@@ -473,26 +478,32 @@ func updateVolumeMountsFromMap(volumeMounts []corev1.VolumeMount, toUpdate *util
 
 	for i := range volumeMounts {
 		volumeMount := &volumeMounts[i]
-		name, present := toUpdate.GetString(volumeMount.MountPath)
+		mountInfo, present := toUpdate.Get(volumeMount.MountPath)
 
 		if present {
+			volumeMountInfo := mountInfo.(*MountInfo)
+			name := volumeMountInfo.VolumeName
 			if !existsVolumeNameInVolumes(name, volumes) {
 				return nil, fmt.Errorf("There is no volume matched with %q", name)
 			}
 
 			volumeMount.ReadOnly = true
 			volumeMount.Name = name
+			volumeMount.SubPath = volumeMountInfo.SubPath
 			set[volumeMount.MountPath] = true
 		}
 	}
 
 	it := toUpdate.Iterator()
-	for mountPath, name, ok := it.NextString(); ok; mountPath, name, ok = it.NextString() {
+	for mountPath, mountInfo, ok := it.Next(); ok; mountPath, mountInfo, ok = it.Next() {
+		volumeMountInfo := mountInfo.(*MountInfo)
+		name := volumeMountInfo.VolumeName
 		if !set[mountPath] {
 			volumeMounts = append(volumeMounts, corev1.VolumeMount{
 				Name:      name,
 				ReadOnly:  true,
 				MountPath: mountPath,
+				SubPath:   volumeMountInfo.SubPath,
 			})
 		}
 	}
@@ -658,6 +669,19 @@ func existsVolumeNameInVolumeMounts(volumeName string, volumeMounts []corev1.Vol
 
 // =======================================================================================
 
+func getMountInfo(volume string) *MountInfo {
+	slices := strings.SplitN(volume, "/", 2)
+	if len(slices) == 1 || slices[1] == "" {
+		return &MountInfo{
+			VolumeName: slices[0],
+		}
+	}
+	return &MountInfo{
+		VolumeName: slices[0],
+		SubPath:    slices[1],
+	}
+}
+
 func reviseVolumeInfoAndMountsToUpdate(mountsToUpdate *util.OrderedMap, volumesToUpdate *util.OrderedMap) (*util.OrderedMap, *util.OrderedMap, error) {
 	volumeSourceInfoByName := util.NewOrderedMap() //make(map[string]*volumeSourceInfo)
 	mountsToUpdateRevised := util.NewOrderedMap()  //make(map[string]string)
@@ -668,23 +692,28 @@ func reviseVolumeInfoAndMountsToUpdate(mountsToUpdate *util.OrderedMap, volumesT
 		// slices[1] -> secret, config-map, or volume name
 		slices := strings.SplitN(value, ":", 2)
 		if len(slices) == 1 {
-			mountsToUpdateRevised.Set(path, slices[0])
+			mountInfo := getMountInfo(slices[0])
+			mountsToUpdateRevised.Set(path, mountInfo)
 		} else {
 			switch volumeType := slices[0]; volumeType {
 			case "config-map", "cm":
 				generatedName := util.GenerateVolumeName(path)
+				mountInfo := getMountInfo(slices[1])
 				volumeSourceInfoByName.Set(generatedName, &volumeSourceInfo{
 					volumeSourceType: ConfigMapVolumeSourceType,
-					volumeSourceName: slices[1],
+					volumeSourceName: mountInfo.VolumeName,
 				})
-				mountsToUpdateRevised.Set(path, generatedName)
+				mountInfo.VolumeName = generatedName
+				mountsToUpdateRevised.Set(path, mountInfo)
 			case "secret", "sc":
 				generatedName := util.GenerateVolumeName(path)
+				mountInfo := getMountInfo(slices[1])
 				volumeSourceInfoByName.Set(generatedName, &volumeSourceInfo{
 					volumeSourceType: SecretVolumeSourceType,
-					volumeSourceName: slices[1],
+					volumeSourceName: mountInfo.VolumeName,
 				})
-				mountsToUpdateRevised.Set(path, generatedName)
+				mountInfo.VolumeName = generatedName
+				mountsToUpdateRevised.Set(path, mountInfo)
 
 			default:
 				return nil, nil, fmt.Errorf("unsupported volume type \"%q\"; supported volume types are \"config-map or cm\", \"secret or sc\", and \"volume or vo\"", slices[0])
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9458f79e..76fdb33e 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -150,7 +150,7 @@ github.com/google/go-cmp/cmp/internal/diff
 github.com/google/go-cmp/cmp/internal/flags
 github.com/google/go-cmp/cmp/internal/function
 github.com/google/go-cmp/cmp/internal/value
-# github.com/google/go-containerregistry v0.8.1-0.20220219142810-1571d7fdc46e
+# github.com/google/go-containerregistry v0.8.1-0.20220414143355-892d7a808387
 ## explicit; go 1.17
 github.com/google/go-containerregistry/pkg/name
 # github.com/google/gofuzz v1.2.0
@@ -465,7 +465,7 @@ google.golang.org/appengine/internal/modules
 google.golang.org/appengine/internal/remote_api
 google.golang.org/appengine/internal/urlfetch
 google.golang.org/appengine/urlfetch
-# google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf
+# google.golang.org/genproto v0.0.0-20220301145929-1ac2ace0dbf7
 ## explicit; go 1.15
 google.golang.org/genproto/googleapis/api/httpbody
 google.golang.org/genproto/googleapis/rpc/status
@@ -892,7 +892,7 @@ k8s.io/utils/internal/third_party/forked/golang/net
 k8s.io/utils/net
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/eventing v0.30.1-0.20220413070808-1b90ef335226
+# knative.dev/eventing v0.30.1-0.20220415141711-ff55a456c3f9
 ## explicit; go 1.16
 knative.dev/eventing/pkg/apis/config
 knative.dev/eventing/pkg/apis/duck
@@ -981,8 +981,8 @@ knative.dev/pkg/tracing/config
 knative.dev/pkg/tracing/propagation
 knative.dev/pkg/tracing/propagation/tracecontextb3
 knative.dev/pkg/tracker
-# knative.dev/serving v0.30.1-0.20220413003907-2de1474b55ba
-## explicit; go 1.16
+# knative.dev/serving v0.30.1-0.20220416140111-2e5ca679a71e
+## explicit; go 1.17
 knative.dev/serving/pkg/apis/autoscaling
 knative.dev/serving/pkg/apis/autoscaling/v1alpha1
 knative.dev/serving/pkg/apis/config


Test patch:
diff --git a/pkg/kn/flags/podspec_test.go b/pkg/kn/flags/podspec_test.go
index bf90daf1..005371ff 100644
--- a/pkg/kn/flags/podspec_test.go
+++ b/pkg/kn/flags/podspec_test.go
@@ -136,6 +136,54 @@ func TestPodSpecResolve(t *testing.T) {
 	testCmd.Execute()
 }
 
+func TestPodSpecMountResolveSubPath(t *testing.T) {
+	args := map[string]*MountInfo{
+		"/mydir=cm:my-cm": {
+			VolumeName: "my-cm",
+		},
+		"/mydir=sc:my-sec": {
+			VolumeName: "my-sec",
+		},
+		"/mydir=myvol": {
+			VolumeName: "myvol",
+		},
+
+		"/mydir=cm:my-cm/subpath/to/mount": {
+			VolumeName: "my-cm",
+			SubPath:    "subpath/to/mount",
+		},
+		"/mydir=sc:my-sec/subpath/to/mount": {
+			VolumeName: "my-sec",
+			SubPath:    "subpath/to/mount",
+		},
+		"/mydir=myvol/subpath/to/mount": {
+			VolumeName: "myvol",
+			SubPath:    "subpath/to/mount",
+		},
+	}
+
+	for arg, mountInfo := range args {
+		outBuf := bytes.Buffer{}
+		flags := &PodSpecFlags{}
+		inputArgs := append([]string{"--image", "repo/user/imageID:tag", "--mount"}, arg)
+		testCmd := &cobra.Command{
+			Use: "test",
+			Run: func(cmd *cobra.Command, args []string) {
+				podSpec := &corev1.PodSpec{Containers: []corev1.Container{{}}}
+				err := flags.ResolvePodSpec(podSpec, cmd.Flags(), inputArgs)
+				assert.NilError(t, err)
+				assert.Equal(t, podSpec.Containers[0].VolumeMounts[0].SubPath, mountInfo.SubPath)
+			},
+		}
+		testCmd.SetOut(&outBuf)
+
+		testCmd.SetArgs(inputArgs)
+		flags.AddFlags(testCmd.Flags())
+		flags.AddCreateFlags(testCmd.Flags())
+		testCmd.Execute()
+	}
+}
+
 func TestPodSpecResolveContainers(t *testing.T) {
 	rawInput := `
 containers:
diff --git a/test/e2e/service_test.go b/test/e2e/service_test.go
index c971ac09..2ca4bccb 100644
--- a/test/e2e/service_test.go
+++ b/test/e2e/service_test.go
@@ -18,17 +18,19 @@
 package e2e
 
 import (
+	"encoding/json"
 	"fmt"
 	"strings"
 	"testing"
 
 	"gotest.tools/v3/assert"
-
+	v1 "k8s.io/api/core/v1"
 	"knative.dev/client/lib/test"
 	"knative.dev/client/pkg/util"
 	network "knative.dev/networking/pkg"
 	pkgtest "knative.dev/pkg/test"
 	"knative.dev/serving/pkg/apis/serving"
+	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 func TestService(t *testing.T) {
@@ -70,6 +72,9 @@ func TestService(t *testing.T) {
 	test.ServiceCreate(r, "service2")
 	test.ServiceCreate(r, "ksvc3")
 	serviceDeleteAll(r)
+
+	t.Log("create services with volume mounts and subpaths")
+	serviceCreateWithMount(r)
 }
 
 func serviceCreatePrivate(r *test.KnRunResultCollector, serviceName string) {
@@ -170,3 +175,55 @@ func serviceDeleteAll(r *test.KnRunResultCollector) {
 	// Check if no services present after kn service delete --all.
 	assert.Check(r.T(), strings.Contains(out.Stdout, "No services found."), "Failed to show 'No services found' after kn service delete --all")
 }
+
+func serviceCreateWithMount(r *test.KnRunResultCollector) {
+	it := r.KnTest()
+	kubectl := test.NewKubectl(it.Namespace())
+
+	r.T().Log("create cm test-cm")
+	_, err := kubectl.Run("create", "configmap", "test-cm", "--from-literal=key=value")
+	assert.NilError(r.T(), err)
+
+	r.T().Log("create service with configmap mounted")
+	out := r.KnTest().Kn().Run("service", "create", "test-svc", "--image", pkgtest.ImagePath("helloworld"), "--mount", "/mydir=cm:test-cm")
+	r.AssertNoError(out)
+
+	r.T().Log("update the subpath in mounted cm")
+	out = r.KnTest().Kn().Run("service", "update", "test-svc", "--mount", "/mydir=cm:test-cm/key")
+	r.AssertNoError(out)
+
+	r.T().Log("create secret test-sec")
+	_, err = kubectl.Run("create", "secret", "generic", "test-sec", "--from-literal", "key1=val1")
+	assert.NilError(r.T(), err)
+
+	r.T().Log("update service with a new mount")
+	out = r.KnTest().Kn().Run("service", "update", "test-svc", "--mount", "/mydir2=sc:test-sec/key1")
+	r.AssertNoError(out)
+
+	serviceDescribeMount(r, "test-svc", "/mydir", "key")
+}
+
+func getVolumeMountWithHostPath(svc *servingv1.Service, hostPath string) *v1.VolumeMount {
+	vols := svc.Spec.Template.Spec.Containers[0].VolumeMounts
+
+	for _, v := range vols {
+		if v.MountPath == hostPath {
+			return &v
+		}
+	}
+	return nil
+}
+func serviceDescribeMount(r *test.KnRunResultCollector, serviceName, hostPath, subPath string) {
+	out := r.KnTest().Kn().Run("service", "describe", serviceName, "-o=json")
+	r.AssertNoError(out)
+
+	svc := &servingv1.Service{}
+	assert.NilError(r.T(), json.Unmarshal([]byte(out.Stdout), &svc))
+
+	r.T().Log("check volume mounts not nil")
+	volumeMount := getVolumeMountWithHostPath(svc, hostPath)
+	assert.Check(r.T(), volumeMount != nil)
+
+	r.T().Log("check volume mount subpath is the same as given")
+	assert.Equal(r.T(), subPath, volumeMount.SubPath)
+}