Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions shared/management/client/rest/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ import (
"github.com/netbirdio/netbird/shared/management/http/util"
)

// APIError represents an error response from the management API.
type APIError struct {
StatusCode int
Message string
}

// Error implements the error interface.
func (e *APIError) Error() string {
return e.Message
}

// IsNotFound returns true if the error represents a 404 Not Found response.
func IsNotFound(err error) bool {
var apiErr *APIError
if ok := errors.As(err, &apiErr); ok {
return apiErr.StatusCode == http.StatusNotFound
}
return false
}

// Client Management service HTTP REST API Client
type Client struct {
managementURL string
Expand Down Expand Up @@ -105,6 +125,15 @@ type Client struct {
// Instance NetBird Instance API
// see more: https://docs.netbird.io/api/resources/instance
Instance *InstanceAPI

// ReverseProxyServices NetBird reverse proxy services APIs
ReverseProxyServices *ReverseProxyServicesAPI

// ReverseProxyClusters NetBird reverse proxy clusters APIs
ReverseProxyClusters *ReverseProxyClustersAPI

// ReverseProxyDomains NetBird reverse proxy domains APIs
ReverseProxyDomains *ReverseProxyDomainsAPI
}

// New initialize new Client instance using PAT token
Expand Down Expand Up @@ -160,6 +189,9 @@ func (c *Client) initialize() {
c.IdentityProviders = &IdentityProvidersAPI{c}
c.Ingress = &IngressAPI{c}
c.Instance = &InstanceAPI{c}
c.ReverseProxyServices = &ReverseProxyServicesAPI{c}
c.ReverseProxyClusters = &ReverseProxyClustersAPI{c}
c.ReverseProxyDomains = &ReverseProxyDomainsAPI{c}
}

// NewRequest creates and executes new management API request
Expand Down Expand Up @@ -194,10 +226,12 @@ func (c *Client) NewRequest(ctx context.Context, method, path string, body io.Re
if resp.StatusCode > 299 {
parsedErr, pErr := parseResponse[util.ErrorResponse](resp)
if pErr != nil {

return nil, pErr
}
return nil, errors.New(parsedErr.Message)
return nil, &APIError{
StatusCode: resp.StatusCode,
Message: parsedErr.Message,
}
}

return resp, nil
Expand Down
25 changes: 25 additions & 0 deletions shared/management/client/rest/reverse_proxy_clusters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package rest

import (
"context"

"github.com/netbirdio/netbird/shared/management/http/api"
)

// ReverseProxyClustersAPI APIs for Reverse Proxy Clusters, do not use directly
type ReverseProxyClustersAPI struct {
c *Client
}

// List lists all available proxy clusters
func (a *ReverseProxyClustersAPI) List(ctx context.Context) ([]api.ProxyCluster, error) {
resp, err := a.c.NewRequest(ctx, "GET", "/api/reverse-proxies/clusters", nil, nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[[]api.ProxyCluster](resp)
return ret, err
}
72 changes: 72 additions & 0 deletions shared/management/client/rest/reverse_proxy_domains.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package rest

import (
"bytes"
"context"
"encoding/json"
"net/url"

"github.com/netbirdio/netbird/shared/management/http/api"
)

// ReverseProxyDomainsAPI APIs for Reverse Proxy Domains, do not use directly
type ReverseProxyDomainsAPI struct {
c *Client
}

// List lists all reverse proxy domains
func (a *ReverseProxyDomainsAPI) List(ctx context.Context) ([]api.ReverseProxyDomain, error) {
resp, err := a.c.NewRequest(ctx, "GET", "/api/reverse-proxies/domains", nil, nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[[]api.ReverseProxyDomain](resp)
return ret, err
}

// Create creates a new custom domain
func (a *ReverseProxyDomainsAPI) Create(ctx context.Context, request api.PostApiReverseProxiesDomainsJSONRequestBody) (*api.ReverseProxyDomain, error) {
requestBytes, err := json.Marshal(request)
if err != nil {
return nil, err
}
resp, err := a.c.NewRequest(ctx, "POST", "/api/reverse-proxies/domains", bytes.NewReader(requestBytes), nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[api.ReverseProxyDomain](resp)
if err != nil {
return nil, err
}
return &ret, nil
}

// Delete deletes a custom domain
func (a *ReverseProxyDomainsAPI) Delete(ctx context.Context, domainID string) error {
resp, err := a.c.NewRequest(ctx, "DELETE", "/api/reverse-proxies/domains/"+url.PathEscape(domainID), nil, nil)
if err != nil {
return err
}
if resp.Body != nil {
defer resp.Body.Close()
}
return nil
}

// Validate triggers domain ownership validation for a custom domain
func (a *ReverseProxyDomainsAPI) Validate(ctx context.Context, domainID string) error {
resp, err := a.c.NewRequest(ctx, "GET", "/api/reverse-proxies/domains/"+url.PathEscape(domainID)+"/validate", nil, nil)
if err != nil {
return err
}
if resp.Body != nil {
defer resp.Body.Close()
}
return nil
}
97 changes: 97 additions & 0 deletions shared/management/client/rest/reverse_proxy_services.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package rest

import (
"bytes"
"context"
"encoding/json"
"net/url"

"github.com/netbirdio/netbird/shared/management/http/api"
)

// ReverseProxyServicesAPI APIs for Reverse Proxy Services, do not use directly
type ReverseProxyServicesAPI struct {
c *Client
}

// List lists all reverse proxy services
func (a *ReverseProxyServicesAPI) List(ctx context.Context) ([]api.Service, error) {
resp, err := a.c.NewRequest(ctx, "GET", "/api/reverse-proxies/services", nil, nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[[]api.Service](resp)
return ret, err
}

// Get retrieves a reverse proxy service by ID
func (a *ReverseProxyServicesAPI) Get(ctx context.Context, serviceID string) (*api.Service, error) {
resp, err := a.c.NewRequest(ctx, "GET", "/api/reverse-proxies/services/"+url.PathEscape(serviceID), nil, nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[api.Service](resp)
if err != nil {
return nil, err
}
return &ret, nil
}

// Create creates a new reverse proxy service
func (a *ReverseProxyServicesAPI) Create(ctx context.Context, request api.PostApiReverseProxiesServicesJSONRequestBody) (*api.Service, error) {
requestBytes, err := json.Marshal(request)
if err != nil {
return nil, err
}
resp, err := a.c.NewRequest(ctx, "POST", "/api/reverse-proxies/services", bytes.NewReader(requestBytes), nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[api.Service](resp)
if err != nil {
return nil, err
}
return &ret, nil
}

// Update updates a reverse proxy service
func (a *ReverseProxyServicesAPI) Update(ctx context.Context, serviceID string, request api.PutApiReverseProxiesServicesServiceIdJSONRequestBody) (*api.Service, error) {
requestBytes, err := json.Marshal(request)
if err != nil {
return nil, err
}
resp, err := a.c.NewRequest(ctx, "PUT", "/api/reverse-proxies/services/"+url.PathEscape(serviceID), bytes.NewReader(requestBytes), nil)
if err != nil {
return nil, err
}
if resp.Body != nil {
defer resp.Body.Close()
}
ret, err := parseResponse[api.Service](resp)
if err != nil {
return nil, err
}
return &ret, nil
}

// Delete deletes a reverse proxy service
func (a *ReverseProxyServicesAPI) Delete(ctx context.Context, serviceID string) error {
resp, err := a.c.NewRequest(ctx, "DELETE", "/api/reverse-proxies/services/"+url.PathEscape(serviceID), nil, nil)
if err != nil {
return err
}
if resp.Body != nil {
defer resp.Body.Close()
}

return nil
}
Loading