Repository: google/gvisor
File: runsc/boot/gofer_conf.go (Go)

Code before:

// Set sets the value. Set(String()) should be idempotent.
func (l *GoferMountConfLowerType) Set(v string) error {
	switch v {
	case "none":
		*l = NoneLower
	case "lisafs":
		*l = Lisafs
	case erofs.Name:
		*l = Erofs
	default:
		return fmt.Errorf("invalid gofer mount config lower layer type: %s", v)
	}
	return nil
}

// GoferMountConf describes how a gofer mount is configured in the sandbox.
type GoferMountConf struct {
	Upper     GoferMountConfUpperType `json:"upper"`
	UpperSize string                  `json:"upperSize,omitempty"`
	Lower     GoferMountConfLowerType `json:"lower"`
}

// String returns a human-readable string representing the gofer mount config.
func (g GoferMountConf) String() string {
	return fmt.Sprintf("%s:%s:upperSize=%s", g.Lower, g.Upper, g.UpperSize)
}

// Set sets the value. Set(String()) should be idempotent.
func (g *GoferMountConf) Set(v string) error {
	parts := strings.Split(v, ":")
	if len(parts) != 3 {
		return fmt.Errorf("invalid gofer mount config format: %q", v)
	}
	if err := g.Lower.Set(parts[0]); err != nil {
		return err
	}
	if err := g.Upper.Set(parts[1]); err != nil {
		return err
	}
	if !g.valid() {
		return fmt.Errorf("invalid gofer mount config: %+v", g)
	}
	sizeArg := parts[2]
	size, cut := strings.CutPrefix(sizeArg, "upperSize=")
	if !cut {
		return fmt.Errorf("invalid gofer mount config format: %q", v)
	}
	g.UpperSize = size
	return nil
}

Review comment (suggestion):
Common case is to not use this option. This string representation shows up in gVisor boot logs as `runsc boot` is invoked with this. There are a lot of gofer mount confs. This will create a lot of noise in flag output. Suggest doing:
```
res := fmt.Sprintf("%s:%s", g.Lower, g.Upper)
if len(g.UpperSize) > 0 {
    res += ":size="+g.UpperSize
}
return res
```

Code after:

// Set sets the value. Set(String()) should be idempotent.
func (l *GoferMountConfLowerType) Set(v string) error {
	switch v {
	case "none":
		*l = NoneLower
	case "lisafs":
		*l = Lisafs
	case erofs.Name:
		*l = Erofs
	default:
		return fmt.Errorf("invalid gofer mount config lower layer type: %s", v)
	}
	return nil
}

// GoferMountConf describes how a gofer mount is configured in the sandbox.
type GoferMountConf struct {
	Lower GoferMountConfLowerType `json:"lower"`
	Upper GoferMountConfUpperType `json:"upper"`
	Size  string                  `json:"size,omitempty"`
}

// String returns a human-readable string representing the gofer mount config.
func (g GoferMountConf) String() string {
	res := fmt.Sprintf("%s:%s", g.Lower, g.Upper)
	if g.Size != "" {
		res += ":size=" + g.Size
	}
	return res
}

// Set sets the value. Set(String()) should be idempotent.
func (g *GoferMountConf) Set(v string) error {
	parts := strings.Split(v, ":")
	if len(parts) < 2 || len(parts) > 3 {
		return fmt.Errorf("invalid gofer mount config format: %q", v)
	}
	if err := g.Lower.Set(parts[0]); err != nil {
		return err
	}
	if err := g.Upper.Set(parts[1]); err != nil {
		return err
	}
	g.Size = ""
	if len(parts) >= 3 {
		sizeArg := parts[2]
		size, cut := strings.CutPrefix(sizeArg, "size=")
		if !cut {
			return fmt.Errorf("invalid gofer mount config format: %q", v)
		}