From 9cb4888738fae88fedcf71eefc587a92672239f9 Mon Sep 17 00:00:00 2001 From: Sivaanand Murugesan Date: Tue, 27 Aug 2024 13:14:21 +0530 Subject: [PATCH] Fixed mack api server --- .gitignore | 6 +- tests/mockApiServer/apiServerMock.go | 89 +++++++++++++++ tests/mockApiServer/routes/common.go | 54 ++++++++++ tests/mockApiServer/routes/mockProjects.go | 108 +++++++++++++++++++ tests/mockApiServer/start_mock_api_server.sh | 4 +- 5 files changed, 256 insertions(+), 5 deletions(-) create mode 100644 tests/mockApiServer/apiServerMock.go create mode 100644 tests/mockApiServer/routes/common.go create mode 100644 tests/mockApiServer/routes/mockProjects.go diff --git a/.gitignore b/.gitignore index a5256285..64cc9d45 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ dist providers # ignore for mock api server -server.crt -server.key -MockAPIServer +mock_server.crt +mock_server.key +MockBuild mock_api_server.log \ No newline at end of file diff --git a/tests/mockApiServer/apiServerMock.go b/tests/mockApiServer/apiServerMock.go new file mode 100644 index 00000000..145905f1 --- /dev/null +++ b/tests/mockApiServer/apiServerMock.go @@ -0,0 +1,89 @@ +package main + +import ( + "encoding/json" + "github.com/gorilla/mux" + "github.com/spectrocloud/terraform-provider-spectrocloud/tests/mockApiServer/routes" + "log" + "net/http" +) + +// API key for authentication +const apiKey = "12345" + +// Aggregate all routes into slices for different servers +var allRoutesPositive []routes.Route +var allRoutesNegative []routes.Route + +// Middleware to check for the API key and log the Project-ID if present +func apiKeyAuthMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("ApiKey") != apiKey { + http.Error(w, "Forbidden", http.StatusForbidden) + return + } + // Log the Project-ID if it is present + if projectID := r.Header.Get("Project-ID"); projectID != "" { + log.Printf("Project-ID: %s", projectID) + } + next.ServeHTTP(w, r) + }) +} + +func main() { + // Create routers for different ports + router8080 := mux.NewRouter() + router8888 := mux.NewRouter() + + // Set up routes for port 8080 + setupRoutes(router8080, allRoutesPositive) + + // Set up routes for port 8888 + setupRoutes(router8888, allRoutesNegative) + + // Start servers on different ports + go func() { + log.Println("Starting server on :8080...") + if err := http.ListenAndServeTLS(":8080", "mock_server.crt", "mock_server.key", router8080); err != nil { + log.Fatalf("Server failed to start on port 8080: %v", err) + } + }() + + log.Println("Starting server on :8888...") + + if err := http.ListenAndServeTLS(":8888", "mock_server.crt", "mock_server.key", router8888); err != nil { + log.Fatalf("Server failed to start on port 8080: %v", err) + } +} + +// setupRoutes configures the given router with the provided routes +func setupRoutes(router *mux.Router, routes []routes.Route) { + // Apply API key middleware to all routes + router.Use(apiKeyAuthMiddleware) + + // Register all routes + for _, route := range routes { + route := route // capture the range variable + + router.HandleFunc(route.Path, func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(route.Response.StatusCode) + if route.Response.Payload != nil { + err := json.NewEncoder(w).Encode(route.Response.Payload) + if err != nil { + return + } + } + }).Methods(route.Method) + } +} + +func init() { + // Initialize routes for port 8080 + allRoutesPositive = append(allRoutesPositive, routes.ProjectRoutes()...) + allRoutesPositive = append(allRoutesPositive, routes.CommonProjectRoutes()...) + + // Initialize routes for port 8888 + allRoutesNegative = append(allRoutesNegative, routes.ProjectNegativeRoutes()...) + allRoutesNegative = append(allRoutesNegative, routes.CommonProjectRoutes()...) +} diff --git a/tests/mockApiServer/routes/common.go b/tests/mockApiServer/routes/common.go new file mode 100644 index 00000000..a824a568 --- /dev/null +++ b/tests/mockApiServer/routes/common.go @@ -0,0 +1,54 @@ +package routes + +import ( + "crypto/rand" + "encoding/hex" + "github.com/spectrocloud/palette-sdk-go/api/models" + "net/http" +) + +// ResponseData defines the structure of mock responses +type ResponseData struct { + StatusCode int + Payload interface{} +} + +// Route defines a mock route with method, path, and response +type Route struct { + Method string + Path string + Response ResponseData +} + +func generateRandomStringUID() string { + bytes := make([]byte, 24/2) + _, err := rand.Read(bytes) + if err != nil { + return "test" + } + return hex.EncodeToString(bytes) +} + +func CommonProjectRoutes() []Route { + return []Route{ + { + Method: "GET", + Path: "/v1/health", + Response: ResponseData{ + StatusCode: http.StatusOK, + Payload: map[string]interface{}{ + "healthy": true, + }, + }, + }, + } +} + +func getError(code string, msg string) models.V1Error { + return models.V1Error{ + Code: code, + Details: nil, + Message: msg, + Ref: "ref-" + generateRandomStringUID(), + } +} diff --git a/tests/mockApiServer/routes/mockProjects.go b/tests/mockApiServer/routes/mockProjects.go new file mode 100644 index 00000000..40ab5fdc --- /dev/null +++ b/tests/mockApiServer/routes/mockProjects.go @@ -0,0 +1,108 @@ +package routes + +import ( + "github.com/spectrocloud/palette-sdk-go/api/models" + "net/http" + "strconv" +) + +func getMockProjectPayload() models.V1Project { + return models.V1Project{ + Metadata: &models.V1ObjectMeta{ + Annotations: nil, + CreationTimestamp: models.V1Time{}, + DeletionTimestamp: models.V1Time{}, + Labels: map[string]string{ + "description": "default project", + }, + LastModifiedTimestamp: models.V1Time{}, + Name: "Default", + UID: generateRandomStringUID(), + }, + Spec: &models.V1ProjectSpec{ + Alerts: nil, + LogoURL: "", + Teams: nil, + Users: nil, + }, + Status: &models.V1ProjectStatus{ + CleanUpStatus: nil, + IsDisabled: false, + }, + } + +} + +func ProjectRoutes() []Route { + return []Route{ + { + Method: "POST", + Path: "/v1/projects", + Response: ResponseData{ + StatusCode: http.StatusCreated, + Payload: map[string]interface{}{"UID": generateRandomStringUID()}, + }, + }, + { + Method: "GET", + Path: "/v1/projects/{uid}", + Response: ResponseData{ + StatusCode: http.StatusOK, + Payload: getMockProjectPayload(), + }, + }, + { + Method: "PUT", + Path: "/v1/projects/{uid}", + Response: ResponseData{ + StatusCode: http.StatusNoContent, + Payload: map[string]interface{}{"UID": generateRandomStringUID()}, + }, + }, + { + Method: "DELETE", + Path: "/v1/projects/{uid}", + Response: ResponseData{ + StatusCode: http.StatusNoContent, + Payload: nil, + }, + }, + } +} + +func ProjectNegativeRoutes() []Route { + return []Route{ + { + Method: "POST", + Path: "/v1/projects", + Response: ResponseData{ + StatusCode: http.StatusConflict, + Payload: getError(strconv.Itoa(http.StatusConflict), "Project already exist"), + }, + }, + { + Method: "GET", + Path: "/v1/projects/{uid}", + Response: ResponseData{ + StatusCode: http.StatusNotFound, + Payload: getError(strconv.Itoa(http.StatusOK), "Project not found"), + }, + }, + { + Method: "PUT", + Path: "/v1/projects/{uid}", + Response: ResponseData{ + StatusCode: http.StatusMethodNotAllowed, + Payload: getError(strconv.Itoa(http.StatusNoContent), "Operation not allowed"), + }, + }, + { + Method: "DELETE", + Path: "/v1/projects/{uid}", + Response: ResponseData{ + StatusCode: http.StatusNotFound, + Payload: getError(strconv.Itoa(http.StatusOK), "Project not found"), + }, + }, + } +} diff --git a/tests/mockApiServer/start_mock_api_server.sh b/tests/mockApiServer/start_mock_api_server.sh index c9ff2b23..dc068d17 100755 --- a/tests/mockApiServer/start_mock_api_server.sh +++ b/tests/mockApiServer/start_mock_api_server.sh @@ -12,7 +12,7 @@ openssl genpkey -algorithm RSA -out mock_server.key -pkeyopt rsa_keygen_bits:204 openssl req -new -x509 -key mock_server.key -out mock_server.crt -days 365 -subj "/C=US/ST=CA/L=City/O=Organization/OU=Department/CN=localhost" # Build the Go project -go build -o MockAPIServer mockApiServer.go +go build -o MockBuild apiServerMock.go # Run the server in the background and redirect output to server.log -nohup ./MockAPIServer > mock_api_server.log 2>&1 & \ No newline at end of file +nohup ./MockBuild > mock_api_server.log 2>&1 & \ No newline at end of file