readysite / hosting / internal / websites / websites.go
1.9 KB
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
}
← Back