Skip to content

Commit

Permalink
Reverse Proxy endpoint changes for VSCode
Browse files Browse the repository at this point in the history
- Added better error management
- Fixed an issue where some error messages were not displayed correctly
- Added an endpoint for the orchestrator to get the reverse proxy config
  • Loading branch information
cjlapao committed Nov 28, 2024
1 parent 77863e9 commit d147340
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 65 deletions.
12 changes: 3 additions & 9 deletions src/controllers/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package controllers

import (
"encoding/json"
"fmt"
"net/http"
"runtime/debug"

Expand All @@ -23,15 +22,10 @@ func GetBaseContext(r *http.Request) *basecontext.BaseContext {

func Recover(ctx basecontext.ApiContext, r *http.Request, w http.ResponseWriter) {
if err := recover(); err != nil {
ctx.LogErrorf("Recovered from panic: %v\n%v", err, debug.Stack())
ctx.LogErrorf("Recovered from panic: %v\n%v", err, string(debug.Stack()))
sysErr := errors.NewWithCodef(http.StatusInternalServerError, "internal server error")
sysErr.NestedError = make([]errors.NestedError, 0)
sysErr.NestedError = append(sysErr.NestedError, errors.NestedError{
Message: fmt.Sprintf("%v", err.(error)),
}, errors.NestedError{
Message: string(debug.Stack()),
})

sysErr.Stack = make([]errors.StackItem, 0)
sysErr.AddStackMessage(string(debug.Stack()))
ReturnApiError(ctx, w, models.NewFromErrorWithCode(sysErr, http.StatusInternalServerError))
}
}
Expand Down
48 changes: 47 additions & 1 deletion src/controllers/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,17 @@ func registerOrchestratorHostsHandlers(ctx basecontext.ApiContext, version strin
WithRequiredClaim(constants.SUPER_USER_ROLE).
WithHandler(DeleteOrchestratorHostCatalogCacheItemVersionHandler()).
Register()

// endregion

// region Reverse Proxy
restapi.NewController().
WithMethod(restapi.GET).
WithVersion(version).
WithPath("/orchestrator/hosts/{id}/reverse-proxy").
WithRequiredClaim(constants.LIST_REVERSE_PROXY_HOSTS_CLAIM).
WithHandler(GetOrchestratorHostReverseProxyConfigHandler()).
Register()

restapi.NewController().
WithMethod(restapi.GET).
WithVersion(version).
Expand Down Expand Up @@ -394,6 +402,7 @@ func registerOrchestratorHostsHandlers(ctx basecontext.ApiContext, version strin
WithRequiredClaim(constants.CONFIGURE_REVERSE_PROXY_CLAIM).
WithHandler(DisableOrchestratorHostReverseProxyHandler()).
Register()
// endregion
}

// @Summary Gets all hosts from the orchestrator
Expand Down Expand Up @@ -1820,6 +1829,43 @@ func CreateOrchestratorVirtualMachineHandler() restapi.ControllerHandler {

// region Orchestrator Reverse Proxy

// @Summary Gets orchestrator host reverse proxy configuration
// @Description This endpoint returns orchestrator host reverse proxy configuration
// @Tags Orchestrator
// @Produce json
// @Param id path string true "Host ID"
// @Success 200 {object} models.ReverseProxy
// @Failure 400 {object} models.ApiErrorResponse
// @Failure 401 {object} models.OAuthErrorResponse
// @Security ApiKeyAuth
// @Security BearerAuth
// @Router /v1/orchestrator/hosts/{id}/reverse-proxy [get]
func GetOrchestratorHostReverseProxyConfigHandler() restapi.ControllerHandler {
return func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
ctx := GetBaseContext(r)
defer Recover(ctx, r, w)

vars := mux.Vars(r)
id := vars["id"]
noCache := false
if r.Header.Get("X-No-Cache") == "true" {
noCache = true
}

orchestratorSvc := orchestrator.NewOrchestratorService(ctx)
response, err := orchestratorSvc.GetHostReverseProxyConfig(ctx, id, "", noCache)
if err != nil {
ReturnApiError(ctx, w, models.NewFromError(err))
return
}

w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(response)
ctx.LogInfof("Successfully got orchestrator host %s reverse proxy config", id)
}
}

// @Summary Gets orchestrator host reverse proxy hosts
// @Description This endpoint returns orchestrator host reverse proxy hosts
// @Tags Orchestrator
Expand Down
6 changes: 3 additions & 3 deletions src/data/models/reverse_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
)

type ReverseProxy struct {
ID string `json:"id"`
ID string `json:"id,omitempty"`
HostID string `json:"host_id,omitempty"`
Enabled bool `json:"enabled"`
Host string `json:"host"`
Port string `json:"port"`
Host string `json:"host,omitempty"`
Port string `json:"port,omitempty"`
}

func (o *ReverseProxy) Diff(source ReverseProxy) bool {
Expand Down
13 changes: 13 additions & 0 deletions src/data/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,3 +532,16 @@ func (j *JsonDatabase) GetOrchestratorReverseProxyHost(ctx basecontext.ApiContex

return nil, ErrOrchestratorReverseProxyHostNotFound
}

func (j *JsonDatabase) GetOrchestratorReverseProxyConfig(ctx basecontext.ApiContext, hostId string) (*models.ReverseProxy, error) {
if !j.IsConnected() {
return nil, ErrDatabaseNotConnected
}

host, err := j.GetOrchestratorHost(ctx, hostId)
if err != nil {
return nil, err
}

return host.ReverseProxy, nil
}
64 changes: 49 additions & 15 deletions src/errors/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package errors

import (
"fmt"
"strings"
)

type SystemError struct {
message string
NestedError []NestedError
Stack []StackItem
Path string
code int
description string
Expand All @@ -25,13 +26,39 @@ func (e SystemError) Error() string {
if e.Path != "" {
msg = fmt.Sprintf("%v, path: %v", msg, e.Path)
}
if len(e.NestedError) > 0 {
msg = fmt.Sprintf("%v, nested errors: %v", msg, e.NestedError)
if len(e.Stack) > 0 {
msg = fmt.Sprintf("%v, nested errors: %v", msg, e.Stack)
}

return msg
}

func (e *SystemError) AddStackError(err error) {
if e.Stack == nil {
e.Stack = make([]StackItem, 0)
}

e.AddStackMessage(err.Error())
}

func (e *SystemError) AddStackMessage(msg string) {
if e.Stack == nil {
e.Stack = make([]StackItem, 0)
}

errorMsg := strings.ReplaceAll(msg, "\t", "")
lines := strings.Split(errorMsg, "\n")
for _, line := range lines {
if line == "" {
continue
}

e.Stack = append(e.Stack, StackItem{
Error: line,
})
}
}

func (e SystemError) Message() string {
return e.message
}
Expand Down Expand Up @@ -143,24 +170,31 @@ func NewWithCodeAndNestedErrorf(sysError SystemError, code int, format string, a
message: fmt.Sprintf(format, a...),
code: code,
}
err.NestedError = make([]NestedError, 0)
nestedError := NestedError{
Message: sysError.Message(),
Code: sysError.Code(),
Path: sysError.Path,
Description: sysError.Description(),
err.Stack = make([]StackItem, 0)

stackErrors := StackItem{
Error: sysError.Message(),
}
if sysError.Code() != 0 {
stackErrors.Code = &sysError.code
}
if sysError.Description() != "" {
stackErrors.Description = &sysError.description
}
if sysError.Path != "" {
stackErrors.Path = &sysError.Path
}

err.NestedError = append(err.NestedError, nestedError)
if len(sysError.NestedError) > 0 {
for _, nestedError := range sysError.NestedError {
nestedError := NestedError{
Message: nestedError.Message,
err.Stack = append(err.Stack, stackErrors)
if len(sysError.Stack) > 0 {
for _, nestedError := range sysError.Stack {
nestedError := StackItem{
Error: nestedError.Error,
Code: nestedError.Code,
Path: nestedError.Path,
Description: nestedError.Description,
}
err.NestedError = append(err.NestedError, nestedError)
err.Stack = append(err.Stack, nestedError)
}
}

Expand Down
8 changes: 0 additions & 8 deletions src/errors/nested_error.go

This file was deleted.

25 changes: 25 additions & 0 deletions src/errors/stack_item.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package errors

type StackItem struct {
Error string
Path *string
Code *int
Description *string
}

func NewStackItem(err SystemError) StackItem {
stackItem := StackItem{
Error: err.Message(),
}
if err.Code() != 0 {
stackItem.Code = &err.code
}
if err.Description() != "" {
stackItem.Description = &err.description
}
if err.Path != "" {
stackItem.Path = &err.Path
}

return stackItem
}
77 changes: 48 additions & 29 deletions src/models/api_error_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import (
)

type ApiErrorStack struct {
Message string `json:"message"`
Error string `json:"error"`
Description string `json:"description,omitempty"`
Path string `json:"path,omitempty"`
Code int `json:"code"`
Code int `json:"code,omitempty"`
}

type ApiErrorResponse struct {
Message string `json:"message"`
Stack []ApiErrorStack `json:"stack,omitempty"`
Code int `json:"code"`
Code int `json:"code,omitempty"`
}

func IsSystemError(err error) bool {
Expand Down Expand Up @@ -69,26 +69,24 @@ func NewFromErrorWithCode(err error, code int) ApiErrorResponse {
Code: code,
}
if IsSystemError(err) {
sysError, ok := err.(errors.SystemError)
if ok {
message.Message = sysError.Message()
if len(sysError.NestedError) > 0 {
for _, nestedError := range sysError.NestedError {
stack := ApiErrorStack{
Message: nestedError.Message,
}
if nestedError.Path != "" {
stack.Path = nestedError.Path
}
if nestedError.Code != 0 {
stack.Code = nestedError.Code
}
if nestedError.Description != "" {
stack.Description = nestedError.Description
}

message.Stack = append(message.Stack, stack)
sysError := extractSystemError(err)
message.Message = sysError.Message()
if len(sysError.Stack) > 0 {
for _, nestedError := range sysError.Stack {
stack := ApiErrorStack{
Error: nestedError.Error,
}
if nestedError.Path != nil {
stack.Path = *nestedError.Path
}
if nestedError.Code != nil {
stack.Code = *nestedError.Code
}
if nestedError.Description != nil {
stack.Description = *nestedError.Description
}

message.Stack = append(message.Stack, stack)
}
}
} else {
Expand All @@ -101,17 +99,38 @@ func NewFromErrorWithCode(err error, code int) ApiErrorResponse {
func (r *ApiErrorResponse) ToError() *errors.SystemError {
err := errors.NewWithCode(r.Message, r.Code)
if len(r.Stack) > 0 {
err.NestedError = make([]errors.NestedError, 0)
err.Stack = make([]errors.StackItem, 0)
for _, stack := range r.Stack {
nestedError := errors.NestedError{
Message: stack.Message,
Code: stack.Code,
Path: stack.Path,
Description: stack.Description,
nestedError := errors.StackItem{
Error: stack.Error,
}
if stack.Path != "" {
nestedError.Path = &stack.Path
}
if stack.Code != 0 {
nestedError.Code = &stack.Code
}
if stack.Description != "" {
nestedError.Description = &stack.Description
}
err.NestedError = append(err.NestedError, nestedError)
err.Stack = append(err.Stack, nestedError)
}
}

return err
}

func extractSystemError(err error) *errors.SystemError {
if IsSystemError(err) {
sysError, ok := err.(errors.SystemError)
if !ok {
sysErrorP, ok := err.(*errors.SystemError)
if ok {
sysError = *sysErrorP
}
}
return &sysError
}

return nil
}
Loading

0 comments on commit d147340

Please sign in to comment.