tested real proxmox connection
--> passed
This commit is contained in:
@@ -125,6 +125,9 @@ func (h Handler) ListTenantAudit(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusInternalServerError, "audit_list_failed")
|
||||
return
|
||||
}
|
||||
if entries == nil {
|
||||
entries = []Entry{}
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"data": entries,
|
||||
@@ -141,4 +144,4 @@ func writeJSON(w http.ResponseWriter, status int, body any) {
|
||||
|
||||
func writeError(w http.ResponseWriter, status int, message string) {
|
||||
writeJSON(w, status, map[string]string{"error": message})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,31 @@ func TestListTenantAuditReturnsEntries(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListTenantAuditReturnsEmptyArray(t *testing.T) {
|
||||
handler := NewHandler(&stubRepository{})
|
||||
req := requestWithPrincipalAndMembership(http.MethodGet, "/tenants/tenant-1/audit", "tenant-1", "owner")
|
||||
req.SetPathValue("tenantID", "tenant-1")
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.ListTenantAudit(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK)
|
||||
}
|
||||
var response struct {
|
||||
Data []Entry `json:"data"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil {
|
||||
t.Fatalf("unmarshal response: %v", err)
|
||||
}
|
||||
if response.Data == nil {
|
||||
t.Fatalf("data = nil, want empty array")
|
||||
}
|
||||
if len(response.Data) != 0 {
|
||||
t.Fatalf("len(data) = %d, want 0", len(response.Data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestListTenantAuditReturnsForbiddenForViewer(t *testing.T) {
|
||||
handler := NewHandler(&stubRepository{})
|
||||
req := requestWithPrincipalAndMembership(http.MethodGet, "/tenants/tenant-1/audit", "tenant-1", "viewer")
|
||||
@@ -84,4 +109,4 @@ type stubRepository struct {
|
||||
|
||||
func (s *stubRepository) ListTenantAudit(_ context.Context, _ string, _ int, _ int) ([]Entry, error) {
|
||||
return s.entries, s.err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ func (h Handler) ListTemplates(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusInternalServerError, "templates_list_failed")
|
||||
return
|
||||
}
|
||||
if templates == nil {
|
||||
templates = []Template{}
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string][]Template{"data": templates})
|
||||
}
|
||||
@@ -186,4 +189,4 @@ func writeJSON(w http.ResponseWriter, status int, body any) {
|
||||
|
||||
func writeError(w http.ResponseWriter, status int, message string) {
|
||||
writeJSON(w, status, map[string]string{"error": message})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestListTemplatesReturnsTemplates(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListTemplatesReturnsEmptyList(t *testing.T) {
|
||||
handler := NewHandler(&stubRepository{templates: []Template{}})
|
||||
handler := NewHandler(&stubRepository{})
|
||||
req := httptest.NewRequest(http.MethodGet, "/internal/templates", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
@@ -57,6 +57,9 @@ func TestListTemplatesReturnsEmptyList(t *testing.T) {
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK)
|
||||
}
|
||||
if got := rec.Body.String(); got != "{\"data\":[]}\n" {
|
||||
t.Fatalf("body = %q, want empty data array", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateTemplateReturnsCreated(t *testing.T) {
|
||||
@@ -205,4 +208,4 @@ func (s *stubRepository) Upsert(_ context.Context, _ Template) (Template, error)
|
||||
|
||||
func (s *stubRepository) Delete(_ context.Context, _ string) (bool, error) {
|
||||
return s.deleteResult, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,9 @@ func (h Handler) ListProjectVMs(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusNotFound, "project_not_found")
|
||||
return
|
||||
}
|
||||
if vms == nil {
|
||||
vms = []VM{}
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string][]VM{"data": vms})
|
||||
}
|
||||
|
||||
@@ -57,6 +57,22 @@ func TestListProjectVMsReturnsVisibleVMs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestListProjectVMsReturnsEmptyArray(t *testing.T) {
|
||||
handler := NewHandler(&stubRepository{listFound: true})
|
||||
req := requestWithPrincipal(http.MethodGet, "/projects/project-1/vms")
|
||||
req.SetPathValue("projectID", "project-1")
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
handler.ListProjectVMs(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK)
|
||||
}
|
||||
if got := rec.Body.String(); got != "{\"data\":[]}\n" {
|
||||
t.Fatalf("body = %q, want empty data array", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListProjectVMsReturnsNotFoundForInaccessibleProject(t *testing.T) {
|
||||
handler := NewHandler(&stubRepository{listFound: false})
|
||||
req := requestWithPrincipal(http.MethodGet, "/projects/project-1/vms")
|
||||
|
||||
@@ -27,6 +27,8 @@ type ProvisionClientFactory func(cluster.Cluster) (ProvisionProxmoxClient, error
|
||||
|
||||
type ProvisionProxmoxClient interface {
|
||||
CloneVM(ctx context.Context, node string, templateVMID int, newVMID int, name string) (string, error)
|
||||
ConfigureHardware(ctx context.Context, node string, vmid int, cfg proxmox.HardwareConfig) (string, error)
|
||||
ResizeDisk(ctx context.Context, node string, vmid int, disk string, sizeGB int) (string, error)
|
||||
ConfigureCloudInit(ctx context.Context, node string, vmid int, cfg proxmox.CloudInitConfig) (string, error)
|
||||
StartVM(ctx context.Context, node string, vmid int) (string, error)
|
||||
StopVM(ctx context.Context, node string, vmid int) (string, error)
|
||||
@@ -174,15 +176,15 @@ func (h Handler) CreateVM(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
vm, err := h.repository.InsertVM(r.Context(), InsertVMRecord{
|
||||
ProjectID: projectID,
|
||||
ClusterID: template.ClusterID,
|
||||
ProxmoxVMID: vmid,
|
||||
Node: req.Node,
|
||||
Name: req.Name,
|
||||
Status: "provisioning",
|
||||
VCPU: req.VCPU,
|
||||
RAMMB: req.RAMMB,
|
||||
DiskGB: req.DiskGB,
|
||||
ProjectID: projectID,
|
||||
ClusterID: template.ClusterID,
|
||||
ProxmoxVMID: vmid,
|
||||
Node: req.Node,
|
||||
Name: req.Name,
|
||||
Status: "provisioning",
|
||||
VCPU: req.VCPU,
|
||||
RAMMB: req.RAMMB,
|
||||
DiskGB: req.DiskGB,
|
||||
})
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "vm_insert_failed")
|
||||
@@ -211,6 +213,19 @@ func (h Handler) CreateVM(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := proxmoxClient.ConfigureHardware(r.Context(), req.Node, vmid, proxmox.HardwareConfig{
|
||||
Cores: req.VCPU,
|
||||
Memory: req.RAMMB,
|
||||
}); err != nil {
|
||||
writeError(w, http.StatusBadGateway, "proxmox_hardware_failed")
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := proxmoxClient.ResizeDisk(r.Context(), req.Node, vmid, "scsi0", req.DiskGB); err != nil {
|
||||
writeError(w, http.StatusBadGateway, "proxmox_resize_failed")
|
||||
return
|
||||
}
|
||||
|
||||
ciCfg := proxmox.CloudInitConfig{
|
||||
CIUser: req.CIUser,
|
||||
IPConfig0: req.IPConfig0,
|
||||
@@ -273,23 +288,23 @@ func (h Handler) CreateVM(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusAccepted, map[string]any{
|
||||
"vm": vm,
|
||||
"upid": startUPID,
|
||||
"clone_upid": cloneUPID,
|
||||
"status": "provisioning",
|
||||
"vm": vm,
|
||||
"upid": startUPID,
|
||||
"clone_upid": cloneUPID,
|
||||
"status": "provisioning",
|
||||
})
|
||||
}
|
||||
|
||||
type createVMRequest struct {
|
||||
Name string `json:"name"`
|
||||
Name string `json:"name"`
|
||||
TemplateID string `json:"template_id"`
|
||||
Node string `json:"node"`
|
||||
VCPU int `json:"vcpu"`
|
||||
RAMMB int `json:"ram_mb"`
|
||||
DiskGB int `json:"disk_gb"`
|
||||
SSHKeyID string `json:"ssh_key_id"`
|
||||
CIUser string `json:"ci_user"`
|
||||
IPConfig0 string `json:"ip_config0"`
|
||||
Node string `json:"node"`
|
||||
VCPU int `json:"vcpu"`
|
||||
RAMMB int `json:"ram_mb"`
|
||||
DiskGB int `json:"disk_gb"`
|
||||
SSHKeyID string `json:"ssh_key_id"`
|
||||
CIUser string `json:"ci_user"`
|
||||
IPConfig0 string `json:"ip_config0"`
|
||||
}
|
||||
|
||||
func DefaultProvisionClientFactory(cluster cluster.Cluster) (ProvisionProxmoxClient, error) {
|
||||
@@ -306,11 +321,11 @@ func NewSQLProvisionAuditWriter(db *sql.DB) SQLProvisionAuditWriter {
|
||||
|
||||
func (w SQLProvisionAuditWriter) WriteVMProvisionAudit(ctx context.Context, event VMProvisionAuditEvent) error {
|
||||
metadata, err := json.Marshal(map[string]any{
|
||||
"cluster_id": event.ClusterID,
|
||||
"template_id": event.TemplateID,
|
||||
"node": event.Node,
|
||||
"upid": event.UPID,
|
||||
"proxmox_vmid": event.ProxmoxVMID,
|
||||
"cluster_id": event.ClusterID,
|
||||
"template_id": event.TemplateID,
|
||||
"node": event.Node,
|
||||
"upid": event.UPID,
|
||||
"proxmox_vmid": event.ProxmoxVMID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -428,4 +443,4 @@ func (h Handler) DeleteVM(w http.ResponseWriter, r *http.Request) {
|
||||
"upid": deleteUPID,
|
||||
"status": "deleting",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user