package main import ( "bytes" "fmt" "log" "os" "os/exec" "strings" "text/template" ) type Services struct { cfg config } func NewServices(cfg config) *Services { return &Services{cfg: cfg} } func (s *Services) AddPrivateKey() error { log.Println("Adding private key") if err := os.MkdirAll(os.ExpandEnv("${HOME}/.ssh"), 0700); err != nil { return err } if err := writeFile(`${HOME}/.ssh/id_rsa`, s.cfg.PrivateKey, 0400); err != nil { return err } return nil } func (s *Services) ConfigureSSH() error { log.Println("Configuring SSH") var bfr bytes.Buffer if err := sshConfigTemplate.Execute(&bfr, struct { Cfg config Home string }{ Cfg: s.cfg, Home: os.Getenv("HOME"), }); err != nil { return err } if err := writeFile(`${HOME}/.ssh/config`, bfr.String(), 0400); err != nil { return err } return nil } func (s *Services) PushRepository() error { sshUrl := fmt.Sprintf(`dokku@%v`, s.cfg.HostName) remoteUrl := fmt.Sprintf(`ssh://%v:22/%v`, sshUrl, s.cfg.AppName) log.Println("Testing Dokku SSH connection") if err := runCmd("ssh", sshUrl, "version"); err != nil { return err } log.Println("SSH connection good. Pushing repository") if err := runCmd("git", "remote", "add", "dokku", remoteUrl); err != nil { return err } if err := runCmd("git", "push", "dokku", "main"); err != nil { return err } return nil } func runCmd(cmd ...string) error { log.Printf(" .. [exec] %v", strings.Join(cmd, " ")) e := exec.Command(cmd[0], cmd[1:]...) e.Stderr = os.Stderr e.Stdout = os.Stdout return e.Run() } func writeFile(path string, content string, mode os.FileMode) error { fullPath := os.ExpandEnv(path) log.Printf(" .. [file] %v (%v bytes)", fullPath, len(content)) return os.WriteFile(fullPath, []byte(content), mode) } var ( sshConfigTemplate = template.Must(template.New("ssh-config").Parse(` Host * StrictHostKeyChecking no Host {{.Cfg.HostName}} HostName {{.Cfg.HostName}} User dokku IdentityFile {{.Home}}/.ssh/id_rsa `)) )