github.com/dnephin/dobi@v0.15.0/config/mount.go (about) 1 package config 2 3 import ( 4 "fmt" 5 6 "github.com/dnephin/configtf" 7 pth "github.com/dnephin/configtf/path" 8 "github.com/dnephin/dobi/utils/fs" 9 ) 10 11 // MountConfig A **mount** resource creates a host bind mount or named volume 12 // mount. 13 // name: mount 14 // example: A mount named ``source`` that mounts the current host directory as 15 // ``/app/code`` in the container. 16 // 17 // .. code-block:: yaml 18 // 19 // mount=source: 20 // bind: . 21 // path: /app/code 22 // 23 // mount=named: 24 // name: app-data 25 // path: /data 26 // 27 type MountConfig struct { 28 // Bind The host path to create and mount. This field supports expansion of 29 // `~` to the current users home directory. 30 Bind string 31 // Path The container path of the mount 32 Path string `config:"required"` 33 // Name The name of a named volume 34 Name string 35 // ReadOnly Set the mount to be read-only 36 ReadOnly bool 37 // File When true create an empty file instead of a directory 38 File bool 39 // Mode The file mode to set on the host file or directory when it is 40 // created. 41 // default: ``0755`` *(for directories)*, ``0644`` *(for files)* 42 Mode int `config:"validate"` 43 Annotations 44 } 45 46 // Dependencies returns an empty list, Mount resources have no dependencies 47 func (c *MountConfig) Dependencies() []string { 48 return []string{} 49 } 50 51 // Validate checks that all fields have acceptable values 52 func (c *MountConfig) Validate(path pth.Path, config *Config) *pth.Error { 53 switch { 54 case c.Bind != "" && c.Name != "": 55 return pth.Errorf(path, "\"name\" and \"bind\" can not be used together") 56 case c.Bind == "" && c.Name == "": 57 return pth.Errorf(path, "One of \"name\" or \"bind\" must be set") 58 case c.Name != "" && c.Mode != 0: 59 return pth.Errorf(path, "\"mode\" can not be used with named volumes") 60 case c.Name != "" && c.File: 61 return pth.Errorf(path, "\"file\" can not be used with named volumes") 62 } 63 return nil 64 } 65 66 // ValidateMode validates Mode and sets a default 67 func (c *MountConfig) ValidateMode() error { 68 if c.Mode != 0 || c.Name != "" { 69 return nil 70 } 71 switch c.File { 72 case true: 73 c.Mode = 0644 74 default: 75 c.Mode = 0755 76 } 77 return nil 78 } 79 80 func (c *MountConfig) String() string { 81 var mount string 82 switch { 83 case c.File: 84 mount = fmt.Sprintf("file %q", c.Bind) 85 case c.Name != "": 86 mount = "named volume" 87 default: 88 mount = fmt.Sprintf("directory %q", c.Bind) 89 } 90 return fmt.Sprintf("Create %s to be mounted at %q", mount, c.Path) 91 } 92 93 // IsBind returns true if the mount is a bind mount to a host directory 94 func (c *MountConfig) IsBind() bool { 95 return c.Bind != "" 96 } 97 98 // Resolve resolves variables in the resource 99 func (c *MountConfig) Resolve(resolver Resolver) (Resource, error) { 100 conf := *c 101 var err error 102 conf.Path, err = resolver.Resolve(c.Path) 103 if err != nil { 104 return &conf, err 105 } 106 conf.Name, err = resolver.Resolve(c.Name) 107 if err != nil { 108 return &conf, err 109 } 110 bind, err := resolver.Resolve(c.Bind) 111 if err != nil { 112 return &conf, err 113 } 114 conf.Bind, err = fs.ExpandUser(bind) 115 return &conf, err 116 } 117 118 func mountFromConfig(name string, values map[string]interface{}) (Resource, error) { 119 mount := &MountConfig{} 120 return mount, configtf.Transform(name, values, mount) 121 } 122 123 func init() { 124 RegisterResource("mount", mountFromConfig) 125 }