No One Can Stop Me Now
This commit is contained in:
287
services/setec-manager/internal/hosting/provider.go
Normal file
287
services/setec-manager/internal/hosting/provider.go
Normal file
@@ -0,0 +1,287 @@
|
||||
package hosting
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrNotSupported is returned when a provider does not support a given operation.
|
||||
var ErrNotSupported = errors.New("operation not supported by this provider")
|
||||
|
||||
// Provider is the interface all hosting service integrations must implement.
|
||||
// Not all providers support all features -- methods should return ErrNotSupported
|
||||
// for unsupported operations.
|
||||
type Provider interface {
|
||||
// Name returns the provider identifier (e.g. "hostinger", "digitalocean").
|
||||
Name() string
|
||||
|
||||
// DisplayName returns a human-readable provider name.
|
||||
DisplayName() string
|
||||
|
||||
// --- Authentication ---
|
||||
|
||||
// Configure applies the given configuration to the provider.
|
||||
Configure(cfg ProviderConfig) error
|
||||
|
||||
// TestConnection verifies that the provider credentials are valid.
|
||||
TestConnection() error
|
||||
|
||||
// --- DNS Management ---
|
||||
|
||||
// ListDNSRecords returns all DNS records for a domain.
|
||||
ListDNSRecords(domain string) ([]DNSRecord, error)
|
||||
|
||||
// CreateDNSRecord adds a single DNS record to a domain.
|
||||
CreateDNSRecord(domain string, record DNSRecord) error
|
||||
|
||||
// UpdateDNSRecords replaces DNS records for a domain. If overwrite is true,
|
||||
// all existing records are removed first.
|
||||
UpdateDNSRecords(domain string, records []DNSRecord, overwrite bool) error
|
||||
|
||||
// DeleteDNSRecord removes DNS records matching the filter.
|
||||
DeleteDNSRecord(domain string, filter DNSRecordFilter) error
|
||||
|
||||
// ResetDNSRecords restores the default DNS records for a domain.
|
||||
ResetDNSRecords(domain string) error
|
||||
|
||||
// --- Domain Management ---
|
||||
|
||||
// ListDomains returns all domains on the account.
|
||||
ListDomains() ([]Domain, error)
|
||||
|
||||
// GetDomain returns detailed information about a single domain.
|
||||
GetDomain(domain string) (*DomainDetail, error)
|
||||
|
||||
// CheckDomainAvailability checks registration availability across TLDs.
|
||||
CheckDomainAvailability(domain string, tlds []string) ([]DomainAvailability, error)
|
||||
|
||||
// PurchaseDomain registers a new domain.
|
||||
PurchaseDomain(req DomainPurchaseRequest) (*OrderResult, error)
|
||||
|
||||
// SetNameservers configures the nameservers for a domain.
|
||||
SetNameservers(domain string, nameservers []string) error
|
||||
|
||||
// EnableDomainLock enables the registrar lock on a domain.
|
||||
EnableDomainLock(domain string) error
|
||||
|
||||
// DisableDomainLock disables the registrar lock on a domain.
|
||||
DisableDomainLock(domain string) error
|
||||
|
||||
// EnablePrivacyProtection enables WHOIS privacy for a domain.
|
||||
EnablePrivacyProtection(domain string) error
|
||||
|
||||
// DisablePrivacyProtection disables WHOIS privacy for a domain.
|
||||
DisablePrivacyProtection(domain string) error
|
||||
|
||||
// --- VPS Management ---
|
||||
|
||||
// ListVMs returns all virtual machines on the account.
|
||||
ListVMs() ([]VirtualMachine, error)
|
||||
|
||||
// GetVM returns details for a single virtual machine.
|
||||
GetVM(id string) (*VirtualMachine, error)
|
||||
|
||||
// CreateVM provisions a new virtual machine.
|
||||
CreateVM(req VMCreateRequest) (*OrderResult, error)
|
||||
|
||||
// ListDataCenters returns available data center locations.
|
||||
ListDataCenters() ([]DataCenter, error)
|
||||
|
||||
// --- SSH Keys ---
|
||||
|
||||
// ListSSHKeys returns all SSH keys on the account.
|
||||
ListSSHKeys() ([]SSHKey, error)
|
||||
|
||||
// AddSSHKey uploads a new SSH public key.
|
||||
AddSSHKey(name, publicKey string) (*SSHKey, error)
|
||||
|
||||
// DeleteSSHKey removes an SSH key by ID.
|
||||
DeleteSSHKey(id string) error
|
||||
|
||||
// --- Billing ---
|
||||
|
||||
// ListSubscriptions returns all active subscriptions.
|
||||
ListSubscriptions() ([]Subscription, error)
|
||||
|
||||
// GetCatalog returns available products in a category.
|
||||
GetCatalog(category string) ([]CatalogItem, error)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Model types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// ProviderConfig holds the credentials and settings needed to connect to a
|
||||
// hosting provider.
|
||||
type ProviderConfig struct {
|
||||
APIKey string `json:"api_key"`
|
||||
APISecret string `json:"api_secret,omitempty"`
|
||||
BaseURL string `json:"base_url,omitempty"`
|
||||
Extra map[string]string `json:"extra,omitempty"`
|
||||
}
|
||||
|
||||
// DNSRecord represents a single DNS record.
|
||||
type DNSRecord struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"` // A, AAAA, CNAME, MX, TXT, etc.
|
||||
Content string `json:"content"`
|
||||
TTL int `json:"ttl,omitempty"` // seconds; 0 means provider default
|
||||
Priority int `json:"priority,omitempty"` // used by MX, SRV
|
||||
}
|
||||
|
||||
// DNSRecordFilter identifies DNS records to match for deletion or lookup.
|
||||
type DNSRecordFilter struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// Domain is a summary of a domain on the account.
|
||||
type Domain struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
// DomainDetail contains full information about a domain registration.
|
||||
type DomainDetail struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Registrar string `json:"registrar"`
|
||||
RegisteredAt time.Time `json:"registered_at"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
Locked bool `json:"locked"`
|
||||
PrivacyProtection bool `json:"privacy_protection"`
|
||||
Nameservers []string `json:"nameservers"`
|
||||
}
|
||||
|
||||
// DomainAvailability reports whether a domain + TLD combination can be
|
||||
// registered and its price.
|
||||
type DomainAvailability struct {
|
||||
Domain string `json:"domain"`
|
||||
TLD string `json:"tld"`
|
||||
Available bool `json:"available"`
|
||||
Price float64 `json:"price"` // in the provider's default currency
|
||||
Currency string `json:"currency"`
|
||||
}
|
||||
|
||||
// DomainPurchaseRequest contains everything needed to register a domain.
|
||||
type DomainPurchaseRequest struct {
|
||||
Domain string `json:"domain"`
|
||||
Years int `json:"years"`
|
||||
AutoRenew bool `json:"auto_renew"`
|
||||
Privacy bool `json:"privacy"`
|
||||
PaymentMethod string `json:"payment_method,omitempty"`
|
||||
}
|
||||
|
||||
// OrderResult is returned after a purchase or provisioning request.
|
||||
type OrderResult struct {
|
||||
OrderID string `json:"order_id"`
|
||||
Status string `json:"status"` // e.g. "pending", "completed", "failed"
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// VirtualMachine represents a VPS instance.
|
||||
type VirtualMachine struct {
|
||||
ID string `json:"id"`
|
||||
Hostname string `json:"hostname"`
|
||||
IPAddress string `json:"ip_address"`
|
||||
IPv6 string `json:"ipv6,omitempty"`
|
||||
Status string `json:"status"` // running, stopped, provisioning, etc.
|
||||
Plan string `json:"plan"`
|
||||
DataCenter string `json:"data_center"`
|
||||
OS string `json:"os"`
|
||||
CPUs int `json:"cpus"`
|
||||
RAMBytes int64 `json:"ram_bytes"`
|
||||
DiskBytes int64 `json:"disk_bytes"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// VMCreateRequest contains everything needed to provision a new VPS.
|
||||
type VMCreateRequest struct {
|
||||
Hostname string `json:"hostname"`
|
||||
Plan string `json:"plan"`
|
||||
DataCenterID string `json:"data_center_id"`
|
||||
OS string `json:"os"`
|
||||
SSHKeyID string `json:"ssh_key_id,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
|
||||
// DataCenter represents a physical hosting location.
|
||||
type DataCenter struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Location string `json:"location"` // city or region
|
||||
Country string `json:"country"`
|
||||
}
|
||||
|
||||
// SSHKey is a stored SSH public key.
|
||||
type SSHKey struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
PublicKey string `json:"public_key"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// Subscription represents a billing subscription.
|
||||
type Subscription struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"` // active, cancelled, expired
|
||||
RenewsAt time.Time `json:"renews_at"`
|
||||
Price float64 `json:"price"`
|
||||
Currency string `json:"currency"`
|
||||
}
|
||||
|
||||
// CatalogItem is a purchasable product or plan.
|
||||
type CatalogItem struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Category string `json:"category"`
|
||||
Price float64 `json:"price"`
|
||||
Currency string `json:"currency"`
|
||||
Features map[string]string `json:"features,omitempty"`
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Provider registry
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
var (
|
||||
mu sync.RWMutex
|
||||
providers = map[string]Provider{}
|
||||
)
|
||||
|
||||
// Register adds a provider to the global registry. It panics if a provider
|
||||
// with the same name is already registered.
|
||||
func Register(p Provider) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
name := p.Name()
|
||||
if _, exists := providers[name]; exists {
|
||||
panic("hosting: provider already registered: " + name)
|
||||
}
|
||||
providers[name] = p
|
||||
}
|
||||
|
||||
// Get returns a registered provider by name.
|
||||
func Get(name string) (Provider, bool) {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
p, ok := providers[name]
|
||||
return p, ok
|
||||
}
|
||||
|
||||
// List returns the names of all registered providers, sorted alphabetically.
|
||||
func List() []string {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
names := make([]string, 0, len(providers))
|
||||
for name := range providers {
|
||||
names = append(names, name)
|
||||
}
|
||||
sort.Strings(names)
|
||||
return names
|
||||
}
|
||||
Reference in New Issue
Block a user