130
plugins/storage/storage.go
Normal file
130
plugins/storage/storage.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
dockeroptions "github.com/dokku/dokku/plugins/docker-options"
|
||||
)
|
||||
|
||||
// MountPhases are the phases where storage mounts are applied
|
||||
var MountPhases = []string{"deploy", "run"}
|
||||
|
||||
// VerifyPaths validates the storage mount path format
|
||||
func VerifyPaths(mountPath string) error {
|
||||
if strings.HasPrefix(mountPath, "/") {
|
||||
matched, err := regexp.MatchString(`^/.*:/`, mountPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !matched {
|
||||
return errors.New("Storage path must be two valid paths divided by colon.")
|
||||
}
|
||||
} else {
|
||||
matched, err := regexp.MatchString(`^[a-zA-Z0-9][a-zA-Z0-9_.-]+:/`, mountPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !matched {
|
||||
return errors.New("Volume name must be two characters or more. Volume name must not contain invalid characters. Storage path must be two valid paths divided by colon.")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckIfPathExists checks if a mount path exists in the specified phases
|
||||
func CheckIfPathExists(appName string, mountPath string, phases []string) bool {
|
||||
for _, phase := range phases {
|
||||
options, err := dockeroptions.GetDockerOptionsForPhase(appName, phase)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, option := range options {
|
||||
if option == fmt.Sprintf("-v %s", mountPath) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetBindMounts returns the bind mounts for an app and phase
|
||||
func GetBindMounts(appName string, phase string) ([]string, error) {
|
||||
mounts := []string{}
|
||||
options, err := dockeroptions.GetDockerOptionsForPhase(appName, phase)
|
||||
if err != nil {
|
||||
return mounts, err
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
if strings.HasPrefix(option, "-v ") {
|
||||
mount := strings.TrimPrefix(option, "-v ")
|
||||
mounts = append(mounts, mount)
|
||||
}
|
||||
}
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
// GetBindMountsForDisplay returns the bind mounts formatted for display
|
||||
func GetBindMountsForDisplay(appName string, phase string) string {
|
||||
mounts, err := GetBindMounts(appName, phase)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
result := []string{}
|
||||
for _, mount := range mounts {
|
||||
result = append(result, fmt.Sprintf("-v %s", mount))
|
||||
}
|
||||
return strings.Join(result, " ")
|
||||
}
|
||||
|
||||
// StorageListEntry represents a storage mount entry for JSON output
|
||||
type StorageListEntry struct {
|
||||
HostPath string `json:"host_path"`
|
||||
ContainerPath string `json:"container_path"`
|
||||
VolumeOptions string `json:"volume_options"`
|
||||
}
|
||||
|
||||
// ParseMountPath parses a mount path into its components
|
||||
func ParseMountPath(mountPath string) StorageListEntry {
|
||||
parts := strings.SplitN(mountPath, ":", 3)
|
||||
entry := StorageListEntry{}
|
||||
|
||||
if len(parts) >= 1 {
|
||||
entry.HostPath = parts[0]
|
||||
}
|
||||
if len(parts) >= 2 {
|
||||
entry.ContainerPath = parts[1]
|
||||
}
|
||||
if len(parts) >= 3 {
|
||||
entry.VolumeOptions = parts[2]
|
||||
}
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
// GetStorageDirectory returns the storage directory path
|
||||
func GetStorageDirectory() string {
|
||||
dokkuLibRoot := common.GetenvWithDefault("DOKKU_LIB_ROOT", "/var/lib/dokku")
|
||||
return fmt.Sprintf("%s/data/storage", dokkuLibRoot)
|
||||
}
|
||||
|
||||
// ValidateDirectoryName validates a storage directory name
|
||||
func ValidateDirectoryName(directory string) error {
|
||||
if directory == "" {
|
||||
return errors.New("Please specify a directory to create")
|
||||
}
|
||||
|
||||
matched, err := regexp.MatchString(`^[A-Za-z0-9_-]+$`, directory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !matched {
|
||||
return errors.New("Directory can only contain the following set of characters: [A-Za-z0-9_-]")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user