Skip to content

Commit a384d6e

Browse files
authored
feat: add noninteractive flow to volume config (knative#2883)
1 parent 347a901 commit a384d6e

File tree

3 files changed

+189
-8
lines changed

3 files changed

+189
-8
lines changed

cmd/config_volumes.go

Lines changed: 147 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,49 @@ func NewConfigVolumesAddCmd() *cobra.Command {
6666
6767
Interactive prompt to add Secrets and ConfigMaps as Volume mounts to the function project
6868
in the current directory or from the directory specified with --path.
69+
70+
For non-interactive usage, use flags to specify the volume type and configuration.
6971
`,
72+
Example: `# Add a ConfigMap volume
73+
{{rootCmdUse}} config volumes add --type=configmap --source=my-config --path=/etc/config
74+
75+
# Add a Secret volume
76+
{{rootCmdUse}} config volumes add --type=secret --source=my-secret --path=/etc/secret
77+
78+
# Add a PersistentVolumeClaim volume
79+
{{rootCmdUse}} config volumes add --type=pvc --source=my-pvc --path=/data
80+
{{rootCmdUse}} config volumes add --type=pvc --source=my-pvc --path=/data --read-only
81+
82+
# Add an EmptyDir volume
83+
{{rootCmdUse}} config volumes add --type=emptydir --path=/tmp/cache
84+
{{rootCmdUse}} config volumes add --type=emptydir --path=/tmp/cache --size=1Gi --medium=Memory`,
7085
SuggestFor: []string{"ad", "create", "insert", "append"},
71-
PreRunE: bindEnv("path", "verbose"),
86+
PreRunE: bindEnv("path", "verbose", "type", "source", "mount-path", "read-only", "size", "medium"),
7287
RunE: func(cmd *cobra.Command, args []string) (err error) {
7388
function, err := initConfigCommand(defaultLoaderSaver)
7489
if err != nil {
7590
return
7691
}
7792

93+
// Check if flags are provided for non-interactive mode
94+
volumeType, _ := cmd.Flags().GetString("type")
95+
if volumeType != "" {
96+
return runAddVolume(cmd, function)
97+
}
98+
99+
// Fall back to interactive mode
78100
return runAddVolumesPrompt(cmd.Context(), function)
79101
},
80102
}
81103

104+
// Add flags for non-interactive mode
105+
cmd.Flags().StringP("type", "t", "", "Volume type: configmap, secret, pvc, or emptydir")
106+
cmd.Flags().StringP("source", "s", "", "Name of the ConfigMap, Secret, or PVC to mount (not used for emptydir)")
107+
cmd.Flags().StringP("mount-path", "m", "", "Path where the volume should be mounted in the container")
108+
cmd.Flags().BoolP("read-only", "r", false, "Mount volume as read-only (only for PVC)")
109+
cmd.Flags().StringP("size", "", "", "Maximum size limit for EmptyDir volume (e.g., 1Gi)")
110+
cmd.Flags().StringP("medium", "", "", "Storage medium for EmptyDir volume: 'Memory' or '' (default)")
111+
82112
return cmd
83113
}
84114

@@ -90,20 +120,34 @@ func NewConfigVolumesRemoveCmd() *cobra.Command {
90120
91121
Interactive prompt to remove Volume mounts from the function project
92122
in the current directory or from the directory specified with --path.
123+
124+
For non-interactive usage, use the --mount-path flag to specify which volume to remove.
93125
`,
126+
Example: `# Remove a volume by its mount path
127+
{{rootCmdUse}} config volumes remove --mount-path=/etc/config`,
94128
Aliases: []string{"rm"},
95129
SuggestFor: []string{"del", "delete", "rmeove"},
96-
PreRunE: bindEnv("path", "verbose"),
130+
PreRunE: bindEnv("path", "verbose", "mount-path"),
97131
RunE: func(cmd *cobra.Command, args []string) (err error) {
98132
function, err := initConfigCommand(defaultLoaderSaver)
99133
if err != nil {
100134
return
101135
}
102136

137+
// Check if mount-path flag is provided for non-interactive mode
138+
mountPath, _ := cmd.Flags().GetString("mount-path")
139+
if mountPath != "" {
140+
return runRemoveVolume(cmd, function, mountPath)
141+
}
142+
143+
// Fall back to interactive mode
103144
return runRemoveVolumesPrompt(function)
104145
},
105146
}
106147

148+
// Add flag for non-interactive mode
149+
cmd.Flags().StringP("mount-path", "m", "", "Path of the volume mount to remove")
150+
107151
return cmd
108152
}
109153

@@ -286,3 +330,104 @@ func runRemoveVolumesPrompt(f fn.Function) (err error) {
286330

287331
return
288332
}
333+
334+
// runAddVolume handles adding volumes using command line flags
335+
func runAddVolume(cmd *cobra.Command, f fn.Function) error {
336+
var (
337+
volumeType, _ = cmd.Flags().GetString("type")
338+
source, _ = cmd.Flags().GetString("source")
339+
mountPath, _ = cmd.Flags().GetString("mount-path")
340+
readOnly, _ = cmd.Flags().GetBool("read-only")
341+
sizeLimit, _ = cmd.Flags().GetString("size")
342+
medium, _ = cmd.Flags().GetString("medium")
343+
)
344+
345+
// Validate mount path
346+
if mountPath == "" {
347+
return fmt.Errorf("--mount-path is required")
348+
}
349+
if !strings.HasPrefix(mountPath, "/") {
350+
return fmt.Errorf("mount path must be an absolute path (start with /)")
351+
}
352+
353+
// Create the volume based on type
354+
newVolume := fn.Volume{Path: &mountPath}
355+
356+
// All volumeTypes except emptydir require a source
357+
if volumeType != "emptydir" && source == "" {
358+
return fmt.Errorf("--source is required for %s volumes", volumeType)
359+
}
360+
361+
switch volumeType {
362+
case "configmap":
363+
newVolume.ConfigMap = &source
364+
case "secret":
365+
newVolume.Secret = &source
366+
case "pvc":
367+
newVolume.PersistentVolumeClaim = &fn.PersistentVolumeClaim{
368+
ClaimName: &source,
369+
ReadOnly: readOnly,
370+
}
371+
if readOnly {
372+
fmt.Fprintf(cmd.OutOrStderr(), "PersistentVolumeClaim will be mounted as read-only")
373+
}
374+
fmt.Fprintf(cmd.OutOrStderr(), "Please ensure the PersistentVolumeClaim extension flag is enabled:\nhttps://knative.dev/docs/serving/configuration/feature-flags/\n")
375+
case "emptydir":
376+
emptyDir := &fn.EmptyDir{}
377+
if sizeLimit != "" {
378+
emptyDir.SizeLimit = &sizeLimit
379+
}
380+
if medium != "" {
381+
if medium != fn.StorageMediumMemory && medium != fn.StorageMediumDefault {
382+
return fmt.Errorf("invalid medium: must be 'Memory' or empty")
383+
}
384+
emptyDir.Medium = medium
385+
}
386+
newVolume.EmptyDir = emptyDir
387+
fmt.Fprintf(cmd.OutOrStderr(), "Please make sure to enable the EmptyDir extension flag:\nhttps://knative.dev/docs/serving/configuration/feature-flags/\n")
388+
389+
default:
390+
return fmt.Errorf("invalid volume type: %s (must be one of: configmap, secret, pvc, emptydir)", volumeType)
391+
}
392+
393+
// Add the volume to the function
394+
f.Run.Volumes = append(f.Run.Volumes, newVolume)
395+
396+
// Save the function
397+
err := f.Write()
398+
if err == nil {
399+
fmt.Printf("Volume entry was added to the function configuration\n")
400+
fmt.Printf("Added: %s\n", newVolume.String())
401+
}
402+
return err
403+
}
404+
405+
// runRemoveVolume handles removing volumes by mount path
406+
func runRemoveVolume(cmd *cobra.Command, f fn.Function, mountPath string) error {
407+
if !strings.HasPrefix(mountPath, "/") {
408+
return fmt.Errorf("mount path must be an absolute path (start with /)")
409+
}
410+
411+
// Find and remove the volume with the specified path
412+
var newVolumes []fn.Volume
413+
removed := false
414+
for _, v := range f.Run.Volumes {
415+
if v.Path != nil && *v.Path == mountPath {
416+
removed = true
417+
} else {
418+
newVolumes = append(newVolumes, v)
419+
}
420+
}
421+
422+
if !removed {
423+
return fmt.Errorf("no volume found with mount path: %s", mountPath)
424+
}
425+
426+
f.Run.Volumes = newVolumes
427+
err := f.Write()
428+
if err == nil {
429+
fmt.Fprintf(cmd.OutOrStderr(), "Volume entry was removed from the function configuration\n")
430+
fmt.Fprintf(cmd.OutOrStderr(), "Removed volume at path: %s\n", mountPath)
431+
}
432+
return err
433+
}

docs/reference/func_config_volumes_add.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,43 @@ Add volume to the function configuration
99
Interactive prompt to add Secrets and ConfigMaps as Volume mounts to the function project
1010
in the current directory or from the directory specified with --path.
1111

12+
For non-interactive usage, use flags to specify the volume type and configuration.
13+
1214

1315
```
1416
func config volumes add
1517
```
1618

19+
### Examples
20+
21+
```
22+
# Add a ConfigMap volume
23+
func config volumes add --type=configmap --source=my-config --path=/etc/config
24+
25+
# Add a Secret volume
26+
func config volumes add --type=secret --source=my-secret --path=/etc/secret
27+
28+
# Add a PersistentVolumeClaim volume
29+
func config volumes add --type=pvc --source=my-pvc --path=/data
30+
func config volumes add --type=pvc --source=my-pvc --path=/data --read-only
31+
32+
# Add an EmptyDir volume
33+
func config volumes add --type=emptydir --path=/tmp/cache
34+
func config volumes add --type=emptydir --path=/tmp/cache --size=1Gi --medium=Memory
35+
```
36+
1737
### Options
1838

1939
```
20-
-h, --help help for add
21-
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
22-
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
40+
-h, --help help for add
41+
--medium string Storage medium for EmptyDir volume: 'Memory' or '' (default)
42+
-m, --mount-path string Path where the volume should be mounted in the container
43+
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
44+
-r, --read-only Mount volume as read-only (only for PVC)
45+
--size string Maximum size limit for EmptyDir volume (e.g., 1Gi)
46+
-s, --source string Name of the ConfigMap, Secret, or PVC to mount (not used for emptydir)
47+
-t, --type string Volume type: configmap, secret, pvc, or emptydir
48+
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
2349
```
2450

2551
### SEE ALSO

docs/reference/func_config_volumes_remove.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,27 @@ Remove volume from the function configuration
99
Interactive prompt to remove Volume mounts from the function project
1010
in the current directory or from the directory specified with --path.
1111

12+
For non-interactive usage, use the --mount-path flag to specify which volume to remove.
13+
1214

1315
```
1416
func config volumes remove
1517
```
1618

19+
### Examples
20+
21+
```
22+
# Remove a volume by its mount path
23+
func config volumes remove --mount-path=/etc/config
24+
```
25+
1726
### Options
1827

1928
```
20-
-h, --help help for remove
21-
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
22-
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
29+
-h, --help help for remove
30+
-m, --mount-path string Path of the volume mount to remove
31+
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
32+
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
2333
```
2434

2535
### SEE ALSO

0 commit comments

Comments
 (0)