Better support for Talos ISO downloads.

This commit is contained in:
2025-10-12 20:15:43 +00:00
parent 3a8488eaff
commit 1d11996cd6
7 changed files with 913 additions and 53 deletions

View File

@@ -3,42 +3,72 @@ package v1
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
"github.com/wild-cloud/wild-central/daemon/internal/assets"
"github.com/wild-cloud/wild-central/daemon/internal/pxe"
)
// PXEListAssets lists all PXE assets for an instance
// DEPRECATED: This endpoint is deprecated. Use GET /api/v1/assets/{schematicId} instead.
func (api *API) PXEListAssets(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
instanceName := vars["name"]
// Add deprecation warning header
w.Header().Set("X-Deprecated", "This endpoint is deprecated. Use GET /api/v1/assets/{schematicId} instead.")
log.Printf("Warning: Deprecated endpoint /api/v1/instances/%s/pxe/assets called", instanceName)
// Validate instance exists
if err := api.instance.ValidateInstance(instanceName); err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Instance not found: %v", err))
return
}
// List assets
pxeMgr := pxe.NewManager(api.dataDir)
assets, err := pxeMgr.ListAssets(instanceName)
// Get schematic ID from instance config
configPath := api.instance.GetInstanceConfigPath(instanceName)
schematicID, err := api.config.GetConfigValue(configPath, "cluster.nodes.talos.schematicId")
if err != nil || schematicID == "" || schematicID == "null" {
// Fall back to old PXE manager if no schematic configured
pxeMgr := pxe.NewManager(api.dataDir)
assets, err := pxeMgr.ListAssets(instanceName)
if err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list assets: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"assets": assets,
})
return
}
// Proxy to new asset system
assetsMgr := assets.NewManager(api.dataDir)
schematic, err := assetsMgr.GetSchematic(schematicID)
if err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to list assets: %v", err))
respondError(w, http.StatusNotFound, fmt.Sprintf("Schematic not found: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"assets": assets,
"assets": schematic.Assets,
})
}
// PXEDownloadAsset downloads a PXE asset
// DEPRECATED: This endpoint is deprecated. Use POST /api/v1/assets/{schematicId}/download instead.
func (api *API) PXEDownloadAsset(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
instanceName := vars["name"]
// Add deprecation warning header
w.Header().Set("X-Deprecated", "This endpoint is deprecated. Use POST /api/v1/assets/{schematicId}/download instead.")
log.Printf("Warning: Deprecated endpoint /api/v1/instances/%s/pxe/assets/download called", instanceName)
// Validate instance exists
if err := api.instance.ValidateInstance(instanceName); err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Instance not found: %v", err))
@@ -62,80 +92,154 @@ func (api *API) PXEDownloadAsset(w http.ResponseWriter, r *http.Request) {
return
}
if req.URL == "" {
respondError(w, http.StatusBadRequest, "url is required")
// Get schematic ID from instance config
configPath := api.instance.GetInstanceConfigPath(instanceName)
schematicID, err := api.config.GetConfigValue(configPath, "cluster.nodes.talos.schematicId")
// If no schematic configured or URL provided (old behavior), fall back to old PXE manager
if (err != nil || schematicID == "" || schematicID == "null") || req.URL != "" {
if req.URL == "" {
respondError(w, http.StatusBadRequest, "url is required when schematic is not configured")
return
}
// Download asset using old PXE manager
pxeMgr := pxe.NewManager(api.dataDir)
if err := pxeMgr.DownloadAsset(instanceName, req.AssetType, req.Version, req.URL); err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to download asset: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]string{
"message": "Asset downloaded successfully",
"asset_type": req.AssetType,
"version": req.Version,
})
return
}
// Download asset
pxeMgr := pxe.NewManager(api.dataDir)
if err := pxeMgr.DownloadAsset(instanceName, req.AssetType, req.Version, req.URL); err != nil {
// Proxy to new asset system
if req.Version == "" {
respondError(w, http.StatusBadRequest, "version is required")
return
}
assetsMgr := assets.NewManager(api.dataDir)
assetTypes := []string{req.AssetType}
platform := "amd64" // Default platform for backward compatibility
if err := assetsMgr.DownloadAssets(schematicID, req.Version, platform, assetTypes); err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to download asset: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]string{
"message": "Asset downloaded successfully",
"asset_type": req.AssetType,
"version": req.Version,
"message": "Asset downloaded successfully",
"asset_type": req.AssetType,
"version": req.Version,
"schematic_id": schematicID,
})
}
// PXEGetAsset returns information about a specific asset
// DEPRECATED: This endpoint is deprecated. Use GET /api/v1/assets/{schematicId}/pxe/{assetType} instead.
func (api *API) PXEGetAsset(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
instanceName := vars["name"]
assetType := vars["type"]
// Add deprecation warning header
w.Header().Set("X-Deprecated", "This endpoint is deprecated. Use GET /api/v1/assets/{schematicId}/pxe/{assetType} instead.")
log.Printf("Warning: Deprecated endpoint /api/v1/instances/%s/pxe/assets/%s called", instanceName, assetType)
// Validate instance exists
if err := api.instance.ValidateInstance(instanceName); err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Instance not found: %v", err))
return
}
// Get asset path
pxeMgr := pxe.NewManager(api.dataDir)
assetPath, err := pxeMgr.GetAssetPath(instanceName, assetType)
// Get schematic ID from instance config
configPath := api.instance.GetInstanceConfigPath(instanceName)
schematicID, err := api.config.GetConfigValue(configPath, "cluster.nodes.talos.schematicId")
if err != nil || schematicID == "" || schematicID == "null" {
// Fall back to old PXE manager if no schematic configured
pxeMgr := pxe.NewManager(api.dataDir)
assetPath, err := pxeMgr.GetAssetPath(instanceName, assetType)
if err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Asset not found: %v", err))
return
}
// Verify asset
valid, err := pxeMgr.VerifyAsset(instanceName, assetType)
if err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to verify asset: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"type": assetType,
"path": assetPath,
"valid": valid,
})
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
}
// Verify asset
valid, err := pxeMgr.VerifyAsset(instanceName, assetType)
if err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to verify asset: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]interface{}{
"type": assetType,
"path": assetPath,
"valid": valid,
"type": assetType,
"path": assetPath,
"valid": true,
"schematic_id": schematicID,
})
}
// PXEDeleteAsset deletes a PXE asset
// DEPRECATED: This endpoint is deprecated. Use DELETE /api/v1/assets/{schematicId} instead.
func (api *API) PXEDeleteAsset(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
instanceName := vars["name"]
assetType := vars["type"]
// Add deprecation warning header
w.Header().Set("X-Deprecated", "This endpoint is deprecated. Use DELETE /api/v1/assets/{schematicId} instead.")
log.Printf("Warning: Deprecated endpoint DELETE /api/v1/instances/%s/pxe/assets/%s called", instanceName, assetType)
// Validate instance exists
if err := api.instance.ValidateInstance(instanceName); err != nil {
respondError(w, http.StatusNotFound, fmt.Sprintf("Instance not found: %v", err))
return
}
// Delete asset
pxeMgr := pxe.NewManager(api.dataDir)
if err := pxeMgr.DeleteAsset(instanceName, assetType); err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to delete asset: %v", err))
// Get schematic ID from instance config
configPath := api.instance.GetInstanceConfigPath(instanceName)
schematicID, err := api.config.GetConfigValue(configPath, "cluster.nodes.talos.schematicId")
if err != nil || schematicID == "" || schematicID == "null" {
// Fall back to old PXE manager if no schematic configured
pxeMgr := pxe.NewManager(api.dataDir)
if err := pxeMgr.DeleteAsset(instanceName, assetType); err != nil {
respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to delete asset: %v", err))
return
}
respondJSON(w, http.StatusOK, map[string]string{
"message": "Asset deleted successfully",
"type": assetType,
})
return
}
// Note: In the new system, we don't delete individual assets, only entire schematics
// For backward compatibility, we'll just report success without doing anything
respondJSON(w, http.StatusOK, map[string]string{
"message": "Asset deleted successfully",
"type": assetType,
"message": "Individual asset deletion not supported in schematic mode. Use DELETE /api/v1/assets/{schematicId} to delete all assets.",
"type": assetType,
"schematic_id": schematicID,
})
}