github.com/ddev/ddev@v1.23.2-0.20240519125000-d824ffe36ff3/pkg/ddevapp/commands.go (about)

     1  package ddevapp
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	dockerImages "github.com/ddev/ddev/pkg/docker"
     9  	"github.com/ddev/ddev/pkg/dockerutil"
    10  	"github.com/ddev/ddev/pkg/globalconfig"
    11  	"github.com/ddev/ddev/pkg/nodeps"
    12  	"github.com/ddev/ddev/pkg/util"
    13  )
    14  
    15  // PopulateGlobalCustomCommandFiles sets up the custom command files in the project
    16  // directories where they need to go.
    17  func PopulateGlobalCustomCommandFiles() error {
    18  	sourceGlobalCommandPath := filepath.Join(globalconfig.GetGlobalDdevDir(), "commands")
    19  	err := os.MkdirAll(sourceGlobalCommandPath, 0755)
    20  	if err != nil {
    21  		return nil
    22  	}
    23  
    24  	// Remove contents of the directory, if the directory exists and has some contents
    25  	commandDirInVolume := "/mnt/ddev-global-cache/global-commands/"
    26  	_, _, err = performTaskInContainer([]string{"rm", "-rf", commandDirInVolume})
    27  	if err != nil {
    28  		return fmt.Errorf("unable to rm %s: %v", commandDirInVolume, err)
    29  	}
    30  
    31  	// Copy commands into container (this will create the directory if it's not there already)
    32  	uid, _, _ := util.GetContainerUIDGid()
    33  	err = dockerutil.CopyIntoVolume(sourceGlobalCommandPath, "ddev-global-cache", "global-commands", uid, "host", false)
    34  	if err != nil {
    35  		return err
    36  	}
    37  
    38  	// Make sure all commands can be executed
    39  	_, stderr, err := performTaskInContainer([]string{"sh", "-c", "chmod -R u+rwx " + commandDirInVolume})
    40  	if err != nil {
    41  		return fmt.Errorf("unable to chmod %s: %v (stderr=%s)", commandDirInVolume, err, stderr)
    42  	}
    43  
    44  	return nil
    45  }
    46  
    47  // performTaskInContainer runs a command in the web container if it's available,
    48  // but uses an anonymous container otherwise.
    49  func performTaskInContainer(command []string) (string, string, error) {
    50  	app, err := GetActiveApp("")
    51  	if err == nil {
    52  		status, _ := app.SiteStatus()
    53  		if status == SiteRunning {
    54  			// Prepare docker exec command
    55  			opts := &ExecOpts{
    56  				RawCmd:    command,
    57  				Tty:       false,
    58  				NoCapture: false,
    59  			}
    60  			return app.Exec(opts)
    61  		}
    62  	}
    63  
    64  	// If there is no running active site, use an anonymous container instead.
    65  	containerName := "performTaskInContainer" + nodeps.RandomString(12)
    66  	uid, _, _ := util.GetContainerUIDGid()
    67  	return dockerutil.RunSimpleContainer(dockerImages.GetWebImage(), containerName, command, nil, nil, []string{"ddev-global-cache:/mnt/ddev-global-cache"}, uid, true, false, map[string]string{"com.ddev.site-name": ""}, nil, &dockerutil.NoHealthCheck)
    68  }