// Creates a ssh connection between the local machine and the remote server. func (p *project) connect(config *ssh.ClientConfig) { fmt.Println("Trying connection...") conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", p.hostname.name, p.port.name), config) errorUtil.CheckError("Failed to dial: ", err) fmt.Println("Connection established.") session, err := conn.NewSession() errorUtil.CheckError("Failed to build session: ", err) defer session.Close() // Loops over the slice of commands to be executed on the remote. for step := range p.typ.program.setup { if p.typ.program.setup[step] == "post-update configuration" { p.secureCopy(conn) } else if p.typ.program.setup[step] == p.projectname.name+".dev" { p.makeDirOnLocal(step) } else if p.typ.program.setup[step] == "git clone" { p.gitOnLocal(step) } else { p.installOnRemote(step, conn) } } }
// Creates a directory on the local machine. Case the directory already exists // remove the old one and runs the function again. func (p *project) makeDirOnLocal(step int) { fmt.Println("Creating directory...") // Get the user home directory path. homeDir := getUserHomeDir() // The dir we want to create. dir := homeDir + string(filepath.Separator) + "sites" + string(filepath.Separator) + p.typ.program.setup[step] // Check if the directory already exists. if _, err := os.Stat(dir); os.IsNotExist(err) { err := os.Mkdir(dir, 0755) errorUtil.CheckError("Failed to create directory.", err) fmt.Println(dir + " successfully created.") } else { fmt.Println(dir + " already exist.\nRemoving old and creating new...") // Remove the old one. if err := os.RemoveAll(dir); err != nil { log.Fatalf("Error removing %s\n%s", dir, err) } p.makeDirOnLocal(step) } }
// Secure Copy a file from local machine to remote host. func (p *project) secureCopy(conn *ssh.Client) { session, err := conn.NewSession() errorUtil.CheckError("Failed to build session: ", err) defer session.Close() var stdoutBuf bytes.Buffer session.Stdout = &stdoutBuf go func() { w, _ := session.StdinPipe() defer w.Close() content := fileUtil.ReadFile("post-update-files" + string(filepath.Separator) + p.typ.program.postUpdateFilename) fmt.Fprintln(w, "C0644", len(content), "post-update") fmt.Fprint(w, content) fmt.Fprint(w, "\x00") }() if err := session.Run("scp -qrt ~/private/repos/" + p.projectname.name + "_hub.git/hooks"); err != nil { log.Fatal("Failed to run SCP: " + err.Error()) } }
func (p *project) installOnRemote(step int, conn *ssh.Client) { // Git and some other programs can send us an unsuccessful exit (< 0) // even if the command was successfully executed on the remote shell. // On these cases, we want to ignore those errors and move onto the next step. ignoredError := "Reason was: ()" // Creates a session over the ssh connection to execute the commands session, err := conn.NewSession() errorUtil.CheckError("Failed to build session: ", err) defer session.Close() var stdoutBuf bytes.Buffer session.Stdout = &stdoutBuf fmt.Println(p.typ.program.setup[step]) err = session.Run(p.typ.program.setup[step]) if err != nil && !strings.Contains(err.Error(), ignoredError) { log.Printf("Command '%s' failed on execution", p.typ.program.setup[step]) log.Fatal("Error on command execution: ", err.Error()) } }
func getUserHomeDir() string { usr, err := user.Current() errorUtil.CheckError("Failed to locate user home directory ", err) return usr.HomeDir }