websites.go
package websites
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/readysite/readysite/hosting/models"
)
// Stop stops a running site container.
func Stop(site *models.Site) error {
name := containerName(site.ID)
if _, err := Docker("stop", name); err != nil {
return fmt.Errorf("stop container: %w", err)
}
return nil
}
// Start starts a stopped site container.
func Start(site *models.Site) error {
name := containerName(site.ID)
if _, err := Docker("start", name); err != nil {
return fmt.Errorf("start container: %w", err)
}
return nil
}
// Destroy removes all infrastructure for a site: container, Caddy config, and reloads.
// Does not update the site's status in the database — caller is responsible for that.
// Returns an error if any critical step fails.
func Destroy(site *models.Site) error {
name := containerName(site.ID)
var errs []string
// Remove container (force, ignore "not found" errors)
if _, err := Docker("rm", "-f", name); err != nil {
errs = append(errs, fmt.Sprintf("remove container: %v", err))
}
// Remove Caddy config
configPath := filepath.Join(SiteConfigDir, site.ID+".caddy")
if err := os.Remove(configPath); err != nil && !os.IsNotExist(err) {
errs = append(errs, fmt.Sprintf("remove config: %v", err))
}
// Reload Caddy to drop the route
if _, err := Docker("exec", "caddy", "caddy", "reload", "--config", "/etc/caddy/Caddyfile"); err != nil {
errs = append(errs, fmt.Sprintf("reload caddy: %v", err))
}
if len(errs) > 0 {
return fmt.Errorf("destroy site %s: %s", site.ID, strings.Join(errs, "; "))
}
return nil
}
// Status returns the runtime status of the site's Docker container.
func Status(site *models.Site) (string, error) {
name := containerName(site.ID)
out, err := Docker("inspect", "--format={{.State.Status}}", name)
if err != nil {
return "", fmt.Errorf("inspect container: %w", err)
}
return out, nil
}