mirror of https://github.com/knative/func.git
feat: add noninteractive flow to volume config (#2883)
This commit is contained in:
parent
347a901c16
commit
a384d6e728
|
|
@ -66,19 +66,49 @@ func NewConfigVolumesAddCmd() *cobra.Command {
|
||||||
|
|
||||||
Interactive prompt to add Secrets and ConfigMaps as Volume mounts to the function project
|
Interactive prompt to add Secrets and ConfigMaps as Volume mounts to the function project
|
||||||
in the current directory or from the directory specified with --path.
|
in the current directory or from the directory specified with --path.
|
||||||
|
|
||||||
|
For non-interactive usage, use flags to specify the volume type and configuration.
|
||||||
`,
|
`,
|
||||||
|
Example: `# Add a ConfigMap volume
|
||||||
|
{{rootCmdUse}} config volumes add --type=configmap --source=my-config --path=/etc/config
|
||||||
|
|
||||||
|
# Add a Secret volume
|
||||||
|
{{rootCmdUse}} config volumes add --type=secret --source=my-secret --path=/etc/secret
|
||||||
|
|
||||||
|
# Add a PersistentVolumeClaim volume
|
||||||
|
{{rootCmdUse}} config volumes add --type=pvc --source=my-pvc --path=/data
|
||||||
|
{{rootCmdUse}} config volumes add --type=pvc --source=my-pvc --path=/data --read-only
|
||||||
|
|
||||||
|
# Add an EmptyDir volume
|
||||||
|
{{rootCmdUse}} config volumes add --type=emptydir --path=/tmp/cache
|
||||||
|
{{rootCmdUse}} config volumes add --type=emptydir --path=/tmp/cache --size=1Gi --medium=Memory`,
|
||||||
SuggestFor: []string{"ad", "create", "insert", "append"},
|
SuggestFor: []string{"ad", "create", "insert", "append"},
|
||||||
PreRunE: bindEnv("path", "verbose"),
|
PreRunE: bindEnv("path", "verbose", "type", "source", "mount-path", "read-only", "size", "medium"),
|
||||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||||
function, err := initConfigCommand(defaultLoaderSaver)
|
function, err := initConfigCommand(defaultLoaderSaver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if flags are provided for non-interactive mode
|
||||||
|
volumeType, _ := cmd.Flags().GetString("type")
|
||||||
|
if volumeType != "" {
|
||||||
|
return runAddVolume(cmd, function)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to interactive mode
|
||||||
return runAddVolumesPrompt(cmd.Context(), function)
|
return runAddVolumesPrompt(cmd.Context(), function)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add flags for non-interactive mode
|
||||||
|
cmd.Flags().StringP("type", "t", "", "Volume type: configmap, secret, pvc, or emptydir")
|
||||||
|
cmd.Flags().StringP("source", "s", "", "Name of the ConfigMap, Secret, or PVC to mount (not used for emptydir)")
|
||||||
|
cmd.Flags().StringP("mount-path", "m", "", "Path where the volume should be mounted in the container")
|
||||||
|
cmd.Flags().BoolP("read-only", "r", false, "Mount volume as read-only (only for PVC)")
|
||||||
|
cmd.Flags().StringP("size", "", "", "Maximum size limit for EmptyDir volume (e.g., 1Gi)")
|
||||||
|
cmd.Flags().StringP("medium", "", "", "Storage medium for EmptyDir volume: 'Memory' or '' (default)")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,20 +120,34 @@ func NewConfigVolumesRemoveCmd() *cobra.Command {
|
||||||
|
|
||||||
Interactive prompt to remove Volume mounts from the function project
|
Interactive prompt to remove Volume mounts from the function project
|
||||||
in the current directory or from the directory specified with --path.
|
in the current directory or from the directory specified with --path.
|
||||||
|
|
||||||
|
For non-interactive usage, use the --mount-path flag to specify which volume to remove.
|
||||||
`,
|
`,
|
||||||
|
Example: `# Remove a volume by its mount path
|
||||||
|
{{rootCmdUse}} config volumes remove --mount-path=/etc/config`,
|
||||||
Aliases: []string{"rm"},
|
Aliases: []string{"rm"},
|
||||||
SuggestFor: []string{"del", "delete", "rmeove"},
|
SuggestFor: []string{"del", "delete", "rmeove"},
|
||||||
PreRunE: bindEnv("path", "verbose"),
|
PreRunE: bindEnv("path", "verbose", "mount-path"),
|
||||||
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||||
function, err := initConfigCommand(defaultLoaderSaver)
|
function, err := initConfigCommand(defaultLoaderSaver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if mount-path flag is provided for non-interactive mode
|
||||||
|
mountPath, _ := cmd.Flags().GetString("mount-path")
|
||||||
|
if mountPath != "" {
|
||||||
|
return runRemoveVolume(cmd, function, mountPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to interactive mode
|
||||||
return runRemoveVolumesPrompt(function)
|
return runRemoveVolumesPrompt(function)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add flag for non-interactive mode
|
||||||
|
cmd.Flags().StringP("mount-path", "m", "", "Path of the volume mount to remove")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,3 +330,104 @@ func runRemoveVolumesPrompt(f fn.Function) (err error) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// runAddVolume handles adding volumes using command line flags
|
||||||
|
func runAddVolume(cmd *cobra.Command, f fn.Function) error {
|
||||||
|
var (
|
||||||
|
volumeType, _ = cmd.Flags().GetString("type")
|
||||||
|
source, _ = cmd.Flags().GetString("source")
|
||||||
|
mountPath, _ = cmd.Flags().GetString("mount-path")
|
||||||
|
readOnly, _ = cmd.Flags().GetBool("read-only")
|
||||||
|
sizeLimit, _ = cmd.Flags().GetString("size")
|
||||||
|
medium, _ = cmd.Flags().GetString("medium")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Validate mount path
|
||||||
|
if mountPath == "" {
|
||||||
|
return fmt.Errorf("--mount-path is required")
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(mountPath, "/") {
|
||||||
|
return fmt.Errorf("mount path must be an absolute path (start with /)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the volume based on type
|
||||||
|
newVolume := fn.Volume{Path: &mountPath}
|
||||||
|
|
||||||
|
// All volumeTypes except emptydir require a source
|
||||||
|
if volumeType != "emptydir" && source == "" {
|
||||||
|
return fmt.Errorf("--source is required for %s volumes", volumeType)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch volumeType {
|
||||||
|
case "configmap":
|
||||||
|
newVolume.ConfigMap = &source
|
||||||
|
case "secret":
|
||||||
|
newVolume.Secret = &source
|
||||||
|
case "pvc":
|
||||||
|
newVolume.PersistentVolumeClaim = &fn.PersistentVolumeClaim{
|
||||||
|
ClaimName: &source,
|
||||||
|
ReadOnly: readOnly,
|
||||||
|
}
|
||||||
|
if readOnly {
|
||||||
|
fmt.Fprintf(cmd.OutOrStderr(), "PersistentVolumeClaim will be mounted as read-only")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(cmd.OutOrStderr(), "Please ensure the PersistentVolumeClaim extension flag is enabled:\nhttps://knative.dev/docs/serving/configuration/feature-flags/\n")
|
||||||
|
case "emptydir":
|
||||||
|
emptyDir := &fn.EmptyDir{}
|
||||||
|
if sizeLimit != "" {
|
||||||
|
emptyDir.SizeLimit = &sizeLimit
|
||||||
|
}
|
||||||
|
if medium != "" {
|
||||||
|
if medium != fn.StorageMediumMemory && medium != fn.StorageMediumDefault {
|
||||||
|
return fmt.Errorf("invalid medium: must be 'Memory' or empty")
|
||||||
|
}
|
||||||
|
emptyDir.Medium = medium
|
||||||
|
}
|
||||||
|
newVolume.EmptyDir = emptyDir
|
||||||
|
fmt.Fprintf(cmd.OutOrStderr(), "Please make sure to enable the EmptyDir extension flag:\nhttps://knative.dev/docs/serving/configuration/feature-flags/\n")
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid volume type: %s (must be one of: configmap, secret, pvc, emptydir)", volumeType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the volume to the function
|
||||||
|
f.Run.Volumes = append(f.Run.Volumes, newVolume)
|
||||||
|
|
||||||
|
// Save the function
|
||||||
|
err := f.Write()
|
||||||
|
if err == nil {
|
||||||
|
fmt.Printf("Volume entry was added to the function configuration\n")
|
||||||
|
fmt.Printf("Added: %s\n", newVolume.String())
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// runRemoveVolume handles removing volumes by mount path
|
||||||
|
func runRemoveVolume(cmd *cobra.Command, f fn.Function, mountPath string) error {
|
||||||
|
if !strings.HasPrefix(mountPath, "/") {
|
||||||
|
return fmt.Errorf("mount path must be an absolute path (start with /)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find and remove the volume with the specified path
|
||||||
|
var newVolumes []fn.Volume
|
||||||
|
removed := false
|
||||||
|
for _, v := range f.Run.Volumes {
|
||||||
|
if v.Path != nil && *v.Path == mountPath {
|
||||||
|
removed = true
|
||||||
|
} else {
|
||||||
|
newVolumes = append(newVolumes, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !removed {
|
||||||
|
return fmt.Errorf("no volume found with mount path: %s", mountPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Run.Volumes = newVolumes
|
||||||
|
err := f.Write()
|
||||||
|
if err == nil {
|
||||||
|
fmt.Fprintf(cmd.OutOrStderr(), "Volume entry was removed from the function configuration\n")
|
||||||
|
fmt.Fprintf(cmd.OutOrStderr(), "Removed volume at path: %s\n", mountPath)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,16 +9,42 @@ Add volume to the function configuration
|
||||||
Interactive prompt to add Secrets and ConfigMaps as Volume mounts to the function project
|
Interactive prompt to add Secrets and ConfigMaps as Volume mounts to the function project
|
||||||
in the current directory or from the directory specified with --path.
|
in the current directory or from the directory specified with --path.
|
||||||
|
|
||||||
|
For non-interactive usage, use flags to specify the volume type and configuration.
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
func config volumes add
|
func config volumes add
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
# Add a ConfigMap volume
|
||||||
|
func config volumes add --type=configmap --source=my-config --path=/etc/config
|
||||||
|
|
||||||
|
# Add a Secret volume
|
||||||
|
func config volumes add --type=secret --source=my-secret --path=/etc/secret
|
||||||
|
|
||||||
|
# Add a PersistentVolumeClaim volume
|
||||||
|
func config volumes add --type=pvc --source=my-pvc --path=/data
|
||||||
|
func config volumes add --type=pvc --source=my-pvc --path=/data --read-only
|
||||||
|
|
||||||
|
# Add an EmptyDir volume
|
||||||
|
func config volumes add --type=emptydir --path=/tmp/cache
|
||||||
|
func config volumes add --type=emptydir --path=/tmp/cache --size=1Gi --medium=Memory
|
||||||
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
-h, --help help for add
|
-h, --help help for add
|
||||||
|
--medium string Storage medium for EmptyDir volume: 'Memory' or '' (default)
|
||||||
|
-m, --mount-path string Path where the volume should be mounted in the container
|
||||||
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
|
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
|
||||||
|
-r, --read-only Mount volume as read-only (only for PVC)
|
||||||
|
--size string Maximum size limit for EmptyDir volume (e.g., 1Gi)
|
||||||
|
-s, --source string Name of the ConfigMap, Secret, or PVC to mount (not used for emptydir)
|
||||||
|
-t, --type string Volume type: configmap, secret, pvc, or emptydir
|
||||||
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
|
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,25 @@ Remove volume from the function configuration
|
||||||
Interactive prompt to remove Volume mounts from the function project
|
Interactive prompt to remove Volume mounts from the function project
|
||||||
in the current directory or from the directory specified with --path.
|
in the current directory or from the directory specified with --path.
|
||||||
|
|
||||||
|
For non-interactive usage, use the --mount-path flag to specify which volume to remove.
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
func config volumes remove
|
func config volumes remove
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
# Remove a volume by its mount path
|
||||||
|
func config volumes remove --mount-path=/etc/config
|
||||||
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
```
|
```
|
||||||
-h, --help help for remove
|
-h, --help help for remove
|
||||||
|
-m, --mount-path string Path of the volume mount to remove
|
||||||
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
|
-p, --path string Path to the function. Default is current directory ($FUNC_PATH)
|
||||||
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
|
-v, --verbose Print verbose logs ($FUNC_VERBOSE)
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue