123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- package handlers
- import (
- // Keep context for future use in actual cloud calls
- "fmt"
- "net/http"
- "git.linuxforward.com/byop/byop-engine/cloud"
- "git.linuxforward.com/byop/byop-engine/models"
- "github.com/gin-gonic/gin"
- )
- // ProviderHandler handles provider-related operations
- type ProviderHandler struct {
- // No specific dependencies for now, but a ProviderService might be added later
- // for more complex logic or if providers are stored in a DB.
- }
- // NewProviderHandler creates a new ProviderHandler
- func NewProviderHandler() *ProviderHandler {
- return &ProviderHandler{}
- }
- // RegisterRoutes registers routes for provider operations
- func (h *ProviderHandler) RegisterRoutes(r *gin.RouterGroup) {
- r.GET("/", h.ListProviders)
- // r.POST("/", h.CreateProvider) // Assuming CreateProvider would involve DB interaction
- r.GET("/:id", h.GetProvider)
- // r.PUT("/:id", h.UpdateProvider) // Assuming UpdateProvider would involve DB interaction
- // r.DELETE("/:id", h.DeleteProvider) // Assuming DeleteProvider would involve DB interaction
- r.GET("/:id/regions", h.GetProviderRegions)
- r.POST("/:id/validate", h.ValidateProviderCredentials)
- }
- // ListProviders returns all supported providers
- func (h *ProviderHandler) ListProviders(c *gin.Context) {
- providers := cloud.GetSupportedProviders() // This returns []string
- if len(providers) == 0 {
- appErr := models.NewErrNotFound("no_providers_found", fmt.Errorf("No supported providers found"))
- models.RespondWithError(c, appErr)
- return
- }
- c.JSON(http.StatusOK, providers) // Returns a JSON array of strings
- }
- // GetProvider returns a specific provider by its ID (name)
- func (h *ProviderHandler) GetProvider(c *gin.Context) {
- ctx := c.Request.Context() // Get context, though not used for current static implementation
- _ = ctx // Avoid unused variable error if not used yet in this specific function
- providerName := c.Param("id")
- supportedProviders := cloud.GetSupportedProviders()
- found := false
- for _, sp := range supportedProviders {
- if sp == providerName {
- found = true
- break
- }
- }
- if !found {
- appErr := models.NewErrNotFound("provider_not_found", fmt.Errorf("Provider with name '%s' not found or not supported", providerName))
- models.RespondWithError(c, appErr)
- return
- }
- // Return basic information about the provider
- c.JSON(http.StatusOK, gin.H{"name": providerName, "status": "supported"})
- }
- // GetProviderRegions returns available regions for a provider
- func (h *ProviderHandler) GetProviderRegions(c *gin.Context) {
- ctx := c.Request.Context() // Get context, to be used for actual cloud calls
- providerName := c.Param("id")
- // Validate if provider is supported
- supportedProviders := cloud.GetSupportedProviders()
- isSupported := false
- for _, sp := range supportedProviders {
- if sp == providerName {
- isSupported = true
- break
- }
- }
- if !isSupported {
- appErr := models.NewErrNotFound("provider_not_supported", fmt.Errorf("Provider '%s' is not supported", providerName))
- models.RespondWithError(c, appErr)
- return
- }
- // Placeholder: Replace with actual calls to cloud.Provider.ListRegions(ctx)
- // For now, using static list. ctx is available for when real calls are made.
- _ = ctx // Explicitly use ctx to avoid "unused" error if no cloud calls yet
- var regions []string
- switch providerName {
- case "aws":
- regions = []string{"us-east-1", "us-west-2", "eu-west-1"} // Example static regions
- case "digitalocean":
- regions = []string{"nyc1", "sfo3", "lon1"} // Example static regions
- case "ovh":
- regions = []string{"GRA", "SBG", "BHS"} // Example static regions
- default:
- // This case should ideally not be hit if validation above is correct
- // and the switch covers all supported providers from cloud.GetSupportedProviders().
- appErr := models.NewErrInternalServer("provider_regions_not_implemented", fmt.Errorf("Regions not implemented for provider '%s'", providerName))
- models.RespondWithError(c, appErr)
- return
- }
- c.JSON(http.StatusOK, regions)
- }
- // ValidateProviderCredentials validates provider credentials
- func (h *ProviderHandler) ValidateProviderCredentials(c *gin.Context) {
- ctx := c.Request.Context() // Get context, to be used for actual cloud calls
- providerName := c.Param("id")
- // Validate if provider is supported
- supportedProviders := cloud.GetSupportedProviders()
- isSupported := false
- for _, sp := range supportedProviders {
- if sp == providerName {
- isSupported = true
- break
- }
- }
- if !isSupported {
- appErr := models.NewErrNotFound("provider_not_supported_for_validation", fmt.Errorf("Provider '%s' is not supported for credential validation", providerName))
- models.RespondWithError(c, appErr)
- return
- }
- var credsBody struct {
- AccessKeyID string `json:"access_key_id"`
- SecretAccessKey string `json:"secret_access_key"`
- Token string `json:"token"` // For AWS STS, DO API token, OVH tokens etc.
- ProjectID string `json:"project_id"` // For GCP, OVH
- Region string `json:"region"` // Optional, might be needed for some validation endpoints
- }
- if err := c.ShouldBindJSON(&credsBody); err != nil {
- appErr := models.NewErrValidation("invalid_credentials_format", map[string]string{"body": "Invalid request body for credentials"}, err)
- models.RespondWithError(c, appErr)
- return
- }
- // Placeholder: Replace with actual calls to a provider method like provider.ValidateCredentials(ctx, creds)
- // ctx is available for when real calls are made.
- _ = ctx // Explicitly use ctx to avoid "unused" error if no cloud calls yet
- var isValid bool
- var validationError error // To store error from actual validation logic
- switch providerName {
- case "aws":
- // e.g., isValid, validationError = cloud.ValidateAWSCredentials(ctx, credsBody.AccessKeyID, credsBody.SecretAccessKey, credsBody.Token, credsBody.Region)
- isValid = true // Assume valid for now
- case "digitalocean":
- // e.g., isValid, validationError = cloud.ValidateDOCredentials(ctx, credsBody.Token)
- isValid = true // Assume valid for now
- case "ovh":
- // e.g., isValid, validationError = cloud.ValidateOVHCredentials(ctx, ...)
- isValid = true // Assume valid for now
- default:
- // This case should ideally not be hit if validation above is correct.
- appErr := models.NewErrInternalServer("provider_validation_not_implemented", fmt.Errorf("Credential validation not implemented for provider '%s'", providerName))
- models.RespondWithError(c, appErr)
- return
- }
- if validationError != nil {
- appErr := models.NewErrInternalServer("credential_validation_error", fmt.Errorf("Error validating credentials for %s: %w", providerName, validationError))
- models.RespondWithError(c, appErr)
- return
- }
- if !isValid {
- appErr := models.NewErrUnauthorized("invalid_provider_credentials", fmt.Errorf("Credentials for provider %s are invalid", providerName))
- models.RespondWithError(c, appErr)
- return
- }
- c.JSON(http.StatusOK, gin.H{"valid": true, "message": "Credentials validated successfully"})
- }
|