ISOs need version AND schema

This commit is contained in:
2025-11-08 22:23:26 +00:00
parent b330b2aea7
commit c623843d53
16 changed files with 170 additions and 174 deletions

View File

@@ -98,13 +98,13 @@ func (api *API) RegisterRoutes(r *mux.Router) {
r.HandleFunc("/api/v1/instances/{name}/nodes/{node}/apply", api.NodeApply).Methods("POST")
r.HandleFunc("/api/v1/instances/{name}/nodes/{node}", api.NodeDelete).Methods("DELETE")
// Asset management
r.HandleFunc("/api/v1/assets", api.AssetsListSchematics).Methods("GET")
r.HandleFunc("/api/v1/assets/{schematicId}", api.AssetsGetSchematic).Methods("GET")
r.HandleFunc("/api/v1/assets/{schematicId}/download", api.AssetsDownload).Methods("POST")
r.HandleFunc("/api/v1/assets/{schematicId}/pxe/{assetType}", api.AssetsServePXE).Methods("GET")
r.HandleFunc("/api/v1/assets/{schematicId}/status", api.AssetsGetStatus).Methods("GET")
r.HandleFunc("/api/v1/assets/{schematicId}", api.AssetsDeleteSchematic).Methods("DELETE")
// PXE Asset management (schematic@version composite key)
r.HandleFunc("/api/v1/pxe/assets", api.AssetsList).Methods("GET")
r.HandleFunc("/api/v1/pxe/assets/{schematicId}/{version}", api.AssetsGet).Methods("GET")
r.HandleFunc("/api/v1/pxe/assets/{schematicId}/{version}/download", api.AssetsDownload).Methods("POST")
r.HandleFunc("/api/v1/pxe/assets/{schematicId}/{version}", api.AssetsDelete).Methods("DELETE")
r.HandleFunc("/api/v1/pxe/assets/{schematicId}/{version}/pxe/{assetType}", api.AssetsServePXE).Methods("GET")
r.HandleFunc("/api/v1/pxe/assets/{schematicId}/{version}/status", api.AssetsGetStatus).Methods("GET")
// Instance-schematic relationship
r.HandleFunc("/api/v1/instances/{name}/schematic", api.SchematicGetInstanceSchematic).Methods("GET")

View File

@@ -11,45 +11,46 @@ import (
"github.com/wild-cloud/wild-central/daemon/internal/assets"
)
// AssetsListSchematics lists all available schematics
func (api *API) AssetsListSchematics(w http.ResponseWriter, r *http.Request) {
// AssetsList lists all available assets (schematic@version combinations)
func (api *API) AssetsList(w http.ResponseWriter, r *http.Request) {
assetsMgr := assets.NewManager(api.dataDir)
schematics, err := assetsMgr.ListSchematics()
assetList, err := assetsMgr.ListAssets()
if err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list schematics: %v", err))
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list assets: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"schematics": schematics,
"assets": assetList,
})
}
// AssetsGetSchematic returns details for a specific schematic
func (api *API) AssetsGetSchematic(w http.ResponseWriter, r *http.Request) {
// AssetsGet returns details for a specific asset (schematic@version)
func (api *API) AssetsGet(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
schematicID := vars["schematicId"]
version := vars["version"]
assetsMgr := assets.NewManager(api.dataDir)
schematic, err := assetsMgr.GetSchematic(schematicID)
asset, err := assetsMgr.GetAsset(schematicID, version)
if err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Schematic not found: %v", err))
respondError(w, http.StatusNotFound, fmt.Sprintf("Asset not found: %v", err))
return
}
respondJSON(w, http.StatusOK, schematic)
respondJSON(w, http.StatusOK, asset)
}
// AssetsDownload downloads assets for a schematic
// AssetsDownload downloads assets for a schematic@version
func (api *API) AssetsDownload(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
schematicID := vars["schematicId"]
version := vars["version"]
// Parse request body
var req struct {
Version string `json:"version"`
Platform string `json:"platform,omitempty"`
AssetTypes []string `json:"asset_types,omitempty"`
}
@@ -59,11 +60,6 @@ func (api *API) AssetsDownload(w http.ResponseWriter, r *http.Request) {
return
}
if req.Version == "" {
respondError(w, http.StatusBadRequest, "version is required")
return
}
// Default platform to amd64 if not specified
if req.Platform == "" {
req.Platform = "amd64"
@@ -71,7 +67,7 @@ func (api *API) AssetsDownload(w http.ResponseWriter, r *http.Request) {
// Download assets
assetsMgr := assets.NewManager(api.dataDir)
if err := assetsMgr.DownloadAssets(schematicID, req.Version, req.Platform, req.AssetTypes); err != nil {
if err := assetsMgr.DownloadAssets(schematicID, version, req.Platform, req.AssetTypes); err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to download assets: %v", err))
return
}
@@ -79,7 +75,7 @@ func (api *API) AssetsDownload(w http.ResponseWriter, r *http.Request) {
respondJSON(w, http.StatusOK, map[string]interface{}{
"message": "Assets downloaded successfully",
"schematic_id": schematicID,
"version": req.Version,
"version": version,
"platform": req.Platform,
})
}
@@ -88,12 +84,13 @@ func (api *API) AssetsDownload(w http.ResponseWriter, r *http.Request) {
func (api *API) AssetsServePXE(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
schematicID := vars["schematicId"]
version := vars["version"]
assetType := vars["assetType"]
assetsMgr := assets.NewManager(api.dataDir)
// Get asset path
assetPath, err := assetsMgr.GetAssetPath(schematicID, assetType)
assetPath, err := assetsMgr.GetAssetPath(schematicID, version, assetType)
if err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Asset not found: %v", err))
return
@@ -137,36 +134,39 @@ func (api *API) AssetsServePXE(w http.ResponseWriter, r *http.Request) {
http.ServeContent(w, r, info.Name(), info.ModTime(), file)
}
// AssetsGetStatus returns download status for a schematic
// AssetsGetStatus returns download status for a schematic@version
func (api *API) AssetsGetStatus(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
schematicID := vars["schematicId"]
version := vars["version"]
assetsMgr := assets.NewManager(api.dataDir)
status, err := assetsMgr.GetAssetStatus(schematicID)
status, err := assetsMgr.GetAssetStatus(schematicID, version)
if err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Schematic not found: %v", err))
respondError(w, http.StatusNotFound, fmt.Sprintf("Asset not found: %v", err))
return
}
respondJSON(w, http.StatusOK, status)
}
// AssetsDeleteSchematic deletes a schematic and all its assets
func (api *API) AssetsDeleteSchematic(w http.ResponseWriter, r *http.Request) {
// AssetsDelete deletes an asset (schematic@version) and all its files
func (api *API) AssetsDelete(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
schematicID := vars["schematicId"]
version := vars["version"]
assetsMgr := assets.NewManager(api.dataDir)
if err := assetsMgr.DeleteSchematic(schematicID); err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to delete schematic: %v", err))
if err := assetsMgr.DeleteAsset(schematicID, version); err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to delete asset: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]string{
"message": "Schematic deleted successfully",
"message": "Asset deleted successfully",
"schematic_id": schematicID,
"version": version,
})
}

View File

@@ -177,7 +177,7 @@ func TestUpdateYAMLFile_NestedStructure(t *testing.T) {
"cloud": map[string]interface{}{
"domain": "test.com",
"dns": map[string]interface{}{
"ip": "1.2.3.4",
"ip": "1.2.3.4",
"port": 53,
},
},
@@ -488,8 +488,8 @@ func TestUpdateYAMLFile_UpdateSecrets(t *testing.T) {
// Update secrets
updateData := map[string]interface{}{
"dbPassword": "secret123",
"apiKey": "key456",
"dbPassword": "secret123",
"apiKey": "key456",
}
updateYAML, _ := yaml.Marshal(updateData)

View File

@@ -45,17 +45,9 @@ func (api *API) PXEListAssets(w http.ResponseWriter, r *http.Request) {
})
return
}
// Proxy to new asset system
assetsMgr := assets.NewManager(api.dataDir)
schematic, err := assetsMgr.GetSchematic(schematicID)
if err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Schematic not found: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"assets": schematic.Assets,
"assets": []interface{}{},
"message": "Please use the new /api/v1/pxe/assets endpoint with both schematic ID and version",
})
}
@@ -184,20 +176,7 @@ func (api *API) PXEGetAsset(w http.ResponseWriter, r *http.Request) {
return
}
// Proxy to new asset system - serve the file directly
assetsMgr := assets.NewManager(api.dataDir)
assetPath, err := assetsMgr.GetAssetPath(schematicID, assetType)
if err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Asset not found: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"type": assetType,
"path": assetPath,
"valid": true,
"schematic_id": schematicID,
})
respondError(w, http.StatusBadRequest, "This deprecated endpoint requires version. Please use /api/v1/pxe/assets/{schematicId}/{version}/pxe/{assetType}")
}
// PXEDeleteAsset deletes a PXE asset

View File

@@ -39,9 +39,9 @@ func (api *API) SchematicGetInstanceSchematic(w http.ResponseWriter, r *http.Req
// If schematic is configured, get asset status
var assetStatus interface{}
if schematicID != "" && schematicID != "null" {
if schematicID != "" && schematicID != "null" && version != "" && version != "null" {
assetsMgr := assets.NewManager(api.dataDir)
status, err := assetsMgr.GetAssetStatus(schematicID)
status, err := assetsMgr.GetAssetStatus(schematicID, version)
if err == nil {
assetStatus = status
}