Snapshot causes a snapshot of the db to be written into the snapshots volume Returns the name of the snapshot and err
(snapshotName string)
| 3101 | // Snapshot causes a snapshot of the db to be written into the snapshots volume |
| 3102 | // Returns the name of the snapshot and err |
| 3103 | func (app *DdevApp) Snapshot(snapshotName string) (string, error) { |
| 3104 | containerSnapshotDirBase := "/var/tmp" |
| 3105 | |
| 3106 | err := app.ProcessHooks("pre-snapshot") |
| 3107 | if err != nil { |
| 3108 | return "", fmt.Errorf("failed to process pre-snapshot hooks: %v", err) |
| 3109 | } |
| 3110 | |
| 3111 | if snapshotName == "" { |
| 3112 | t := time.Now() |
| 3113 | snapshotName = app.Name + "_" + t.Format("20060102150405") |
| 3114 | } |
| 3115 | |
| 3116 | if !regexp.MustCompile(`^[\w-.]+$`).MatchString(snapshotName) { |
| 3117 | return "", fmt.Errorf("invalid snapshot name '%s': it may only contain letters, numbers, hyphens, periods, and underscores", snapshotName) |
| 3118 | } |
| 3119 | |
| 3120 | suffix := ".zst" |
| 3121 | // MariaDB 5.5 is based on Ubuntu 14.04 which lacks zstd support |
| 3122 | if app.Database.Type == nodeps.MariaDB && app.Database.Version == nodeps.MariaDB55 { |
| 3123 | suffix = ".gz" |
| 3124 | } |
| 3125 | snapshotFile := snapshotName + "-" + app.Database.Type + "_" + app.Database.Version + suffix |
| 3126 | |
| 3127 | existingSnapshots, err := app.ListSnapshotNames() |
| 3128 | if err != nil { |
| 3129 | return "", err |
| 3130 | } |
| 3131 | if nodeps.ArrayContainsString(existingSnapshots, snapshotName) { |
| 3132 | return "", fmt.Errorf("snapshot %s already exists, please use another snapshot name or clean up snapshots with `ddev snapshot --cleanup`", snapshotFile) |
| 3133 | } |
| 3134 | |
| 3135 | // Container side has to use path.Join instead of filepath.Join because they are |
| 3136 | // targeted at the Linux filesystem, so won't work with filepath on Windows |
| 3137 | containerSnapshotDir := containerSnapshotDirBase |
| 3138 | |
| 3139 | // Ensure that db container is up. |
| 3140 | err = app.Wait([]string{"db"}) |
| 3141 | if err != nil { |
| 3142 | return "", fmt.Errorf("unable to snapshot database, \nyour db container in project %v is not running. \nPlease start the project if you want to snapshot it. \nIf deleting project, you can delete without a snapshot using \n'ddev delete --omit-snapshot --yes', \nwhich will destroy your database", app.Name) |
| 3143 | } |
| 3144 | |
| 3145 | util.Success("Creating database snapshot %s", snapshotName) |
| 3146 | |
| 3147 | c := getBackupCommand(app, path.Join(containerSnapshotDir, snapshotFile)) |
| 3148 | stdout, stderr, err := app.Exec(&ExecOpts{ |
| 3149 | Service: "db", |
| 3150 | Cmd: fmt.Sprintf(`set -eu -o pipefail; %s `, c), |
| 3151 | }) |
| 3152 | |
| 3153 | if err != nil { |
| 3154 | util.Warning("Failed to create snapshot: %v, stdout=%s, stderr=%s", err, stdout, stderr) |
| 3155 | return "", err |
| 3156 | } |
| 3157 | |
| 3158 | dbContainer, err := GetContainer(app, "db") |
| 3159 | if err != nil { |
| 3160 | return "", err |