// addHostFingerprint adds a host fingerprint to the known_hosts file. func addHostFingerprint(fingerprint string) error { if len(fingerprint) == 0 { return fmt.Errorf("failed to add host fingerprint: empty fingerprint!") } // Get the know_hosts file path. path := config.Config.KnownHostsFilePath() // Create the base directory if not present. err := utils.MkDirIfNotExists(filepath.Dir(path)) if err != nil { return err } err = func() error { // Open the file. f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) if err != nil { return err } defer f.Close() // Append the fingerprint. if _, err = f.WriteString("\n" + fingerprint); err != nil { return err } return nil }() if err != nil { return err } return nil }
// backup the app data. // This method won't lock the taskMutex. You have to handle it! func (a *App) backup() error { // Don't backup during some special app tasks. if a.task == taskCloneSource || a.task == taskUpdate { return fmt.Errorf("can't backup app '%s' during an update task!", a.name) } // Get the app's base backup folder. backupPath := a.BackupDirectoryPath() // Create the base app backup folder if not present. err := utils.MkDirIfNotExists(backupPath) if err != nil { return fmt.Errorf("failed to backup app '%s': %v", a.name, err) } // Create a new backup directory with the current timestamp. backupPath += "/" + strconv.FormatInt(time.Now().Unix(), 10) // Log log.Infof("creating backup of app '%s': %s", a.name, backupPath) // Create a snapshot of the complete app subvolume. err = btrfs.Snapshot(a.path, backupPath, true) if err != nil { return fmt.Errorf("failed to backup app '%s': %v", a.name, err) } return nil }
func setupRunEnvironment(app *App) error { // Get the app's volumes directory path. volumesPath := app.VolumesDirectoryPath() // Create the volumes folder if not present. err := utils.MkDirIfNotExists(volumesPath) if err != nil { return err } // Get the turtlefile. turtlefile, err := app.Turtlefile() if err != nil { return err } // Setup the container volume directories if not present. var path string for _, c := range turtlefile.Containers { // Get all volumes without any suffix... volumes := c.VolumesStripped() if len(volumes) == 0 { continue } // Create the base container volume directory path. path = volumesPath + "/" + c.Name for _, v := range volumes { err = utils.MkDirIfNotExists(filepath.Clean(path+"/"+v), 0750) if err != nil { return err } } } return nil }
// prepareEnv prepares the turtle environment. func prepareEnv() (err error) { // Create the directories if they don't exists. createDirs := []string{ config.Config.AppPath, config.Config.BackupPath, config.Config.TurtlePath, } for _, dir := range createDirs { if err = utils.MkDirIfNotExists(dir); err != nil { return err } } // Initialize and load the apps. if err = apps.LoadApps(); err != nil { return err } return nil }
// Add and register a new turtle App. // A turtle App name should not not contain any whitespaces. func Add(name, sourceURL, branch string) (err error) { var a *App // Cleanup on any error. defer func() { if err == nil || a == nil { return } // Remove the app subvolume if it exists. e, errC := utils.Exists(a.path) if errC != nil { log.Errorf("failed to cleanup failed add app action: %v", errC) } else if e { if errC = btrfs.DeleteSubvolume(a.path); errC != nil { log.Errorf("failed to cleanup failed add app action: %v", errC) } } }() // Lock the mutex. appsMutex.Lock() defer appsMutex.Unlock() // Check if an app with the same name already exists. _, ok := apps[name] if ok { return fmt.Errorf("an App with the name '%s' already exists!", name) } // Create a new app value. a, err = newApp(name) if err != nil { return fmt.Errorf("failed to create add: %v", err) } // Set the app's settings. a.settings.SourceURL = sourceURL a.settings.Branch = branch // Create the app's subvolume. if err = btrfs.CreateSubvolume(a.path); err != nil { return fmt.Errorf("failed to prepare app's environment: %v", err) } // Save the app's settings to the app settings file. if err = a.saveSettings(); err != nil { return fmt.Errorf("failed to prepare app's environment: %v", err) } // Create the source directory. err = utils.MkDirIfNotExists(a.SourceDirectoryPath()) if err != nil { return fmt.Errorf("failed to prepare app's environment: %v", err) } // Clone the source in a new task. if err = a.cloneSource(); err != nil { return err } // Finally add the app to the map. apps[name] = a return nil }