diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index bb9a19c..695856b 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -23,9 +23,9 @@ jobs: strategy: matrix: go: - - "1.21" - "1.22" - "1.23" + - "1.24" steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a2e6636..5b07bdb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,9 +18,9 @@ jobs: go-version: "1.23" - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v8 with: - version: latest + version: v2.1 args: --timeout=5m - name: Check formatting diff --git a/.golangci.yml b/.golangci.yml index dcf7929..96deede 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,22 +1,23 @@ +version: "2" + +run: + timeout: 5m + tests: true + go: "1.23" + linters: enable: - - gofmt - - govet - - revive - - gosimple - - staticcheck - errcheck - - ineffassign - gosec + - govet + - ineffassign - misspell + - revive + - staticcheck - unconvert - -run: - timeout: 5m - tests: true - -issues: - exclude-rules: - - path: _test\.go - linters: - - gosec + - unused + exclusions: + rules: + - path: _test\.go + linters: + - gosec diff --git a/cloudconnexa/access_groups.go b/cloudconnexa/access_groups.go index b0c0091..d2ed0f7 100644 --- a/cloudconnexa/access_groups.go +++ b/cloudconnexa/access_groups.go @@ -1,3 +1,6 @@ +// Package cloudconnexa provides a Go client library for the CloudConnexa API. +// It offers comprehensive functionality for managing VPN networks, hosts, connectors, +// routes, users, and other CloudConnexa resources through a simple Go interface. package cloudconnexa import ( @@ -7,6 +10,8 @@ import ( "net/http" ) +// AccessGroup represents a group of access rules that define network access permissions. +// It contains source and destination rules that determine what resources can access each other. type AccessGroup struct { ID string `json:"id"` Name string `json:"name"` @@ -15,6 +20,8 @@ type AccessGroup struct { Destination []AccessItem `json:"destination"` } +// AccessItem represents a single access rule item that can be either a source or destination. +// It defines what resources are covered by the access rule and their relationships. type AccessItem struct { Type string `json:"type"` AllCovered bool `json:"allCovered"` @@ -22,10 +29,13 @@ type AccessItem struct { Children []string `json:"children,omitempty"` } +// Item represents a basic resource with an identifier. type Item struct { ID string `json:"id"` } +// AccessGroupPageResponse represents a paginated response from the CloudConnexa API +// containing a list of access groups and pagination metadata. type AccessGroupPageResponse struct { Content []AccessGroup `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -36,8 +46,11 @@ type AccessGroupPageResponse struct { TotalPages int `json:"totalPages"` } +// AccessGroupsService handles communication with the CloudConnexa API for access group operations. type AccessGroupsService service +// GetAccessGroupsByPage retrieves a paginated list of access groups from the CloudConnexa API. +// It returns the access groups for the specified page and page size. func (c *AccessGroupsService) GetAccessGroupsByPage(page int, size int) (AccessGroupPageResponse, error) { endpoint := fmt.Sprintf("%s/access-groups?page=%d&size=%d", c.client.GetV1Url(), page, size) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -58,6 +71,8 @@ func (c *AccessGroupsService) GetAccessGroupsByPage(page int, size int) (AccessG return response, nil } +// List retrieves all access groups from the CloudConnexa API. +// It handles pagination internally and returns a complete list of access groups. func (c *AccessGroupsService) List() ([]AccessGroup, error) { var allGroups []AccessGroup page := 0 @@ -78,6 +93,7 @@ func (c *AccessGroupsService) List() ([]AccessGroup, error) { return allGroups, nil } +// Get retrieves a specific access group by its ID from the CloudConnexa API. func (c *AccessGroupsService) Get(id string) (*AccessGroup, error) { endpoint := fmt.Sprintf("%s/access-groups/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -98,6 +114,8 @@ func (c *AccessGroupsService) Get(id string) (*AccessGroup, error) { return &accessGroup, nil } +// Create creates a new access group in the CloudConnexa API. +// It returns the created access group with its assigned ID. func (c *AccessGroupsService) Create(accessGroup *AccessGroup) (*AccessGroup, error) { accessGroupJSON, err := json.Marshal(accessGroup) if err != nil { @@ -124,6 +142,8 @@ func (c *AccessGroupsService) Create(accessGroup *AccessGroup) (*AccessGroup, er return &s, nil } +// Update updates an existing access group in the CloudConnexa API. +// It returns the updated access group. func (c *AccessGroupsService) Update(id string, accessGroup *AccessGroup) (*AccessGroup, error) { accessGroupJSON, err := json.Marshal(accessGroup) if err != nil { @@ -150,6 +170,7 @@ func (c *AccessGroupsService) Update(id string, accessGroup *AccessGroup) (*Acce return &s, nil } +// Delete removes an access group from the CloudConnexa API by its ID. func (c *AccessGroupsService) Delete(id string) error { endpoint := fmt.Sprintf("%s/access-groups/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodDelete, endpoint, nil) diff --git a/cloudconnexa/cloudconnexa.go b/cloudconnexa/cloudconnexa.go index e0ebfae..ececde8 100644 --- a/cloudconnexa/cloudconnexa.go +++ b/cloudconnexa/cloudconnexa.go @@ -17,6 +17,7 @@ const ( userAgent = "cloudconnexa-go" ) +// Client represents a CloudConnexa API client with all service endpoints. type Client struct { client *http.Client @@ -49,10 +50,12 @@ type service struct { client *Client } +// Credentials represents the OAuth2 token response from CloudConnexa API. type Credentials struct { AccessToken string `json:"access_token"` } +// ErrClientResponse represents an error response from the CloudConnexa API. type ErrClientResponse struct { status int body string @@ -62,6 +65,8 @@ func (e ErrClientResponse) Error() string { return fmt.Sprintf("status code: %d, response body: %s", e.status, e.body) } +// NewClient creates a new CloudConnexa API client with the given credentials. +// It authenticates using OAuth2 client credentials flow and returns a configured client. func NewClient(baseURL, clientID, clientSecret string) (*Client, error) { if clientID == "" || clientSecret == "" { return nil, ErrCredentialsRequired @@ -88,7 +93,13 @@ func NewClient(baseURL, clientID, clientSecret string) (*Client, error) { return nil, err } - defer resp.Body.Close() + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil { + // Log the error if you have a logger, otherwise this is acceptable for library code + _ = closeErr + } + }() + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err @@ -126,6 +137,8 @@ func NewClient(baseURL, clientID, clientSecret string) (*Client, error) { return c, nil } +// DoRequest executes an HTTP request with authentication and rate limiting. +// It automatically adds the Bearer token, sets headers, and handles errors. func (c *Client) DoRequest(req *http.Request) ([]byte, error) { err := c.RateLimiter.Wait(context.Background()) if err != nil { @@ -140,7 +153,12 @@ func (c *Client) DoRequest(req *http.Request) ([]byte, error) { if err != nil { return nil, err } - defer res.Body.Close() + defer func() { + if closeErr := res.Body.Close(); closeErr != nil { + // Log the error if you have a logger, otherwise this is acceptable for library code + _ = closeErr + } + }() body, err := io.ReadAll(res.Body) if err != nil { @@ -154,6 +172,7 @@ func (c *Client) DoRequest(req *http.Request) ([]byte, error) { return body, nil } +// GetV1Url returns the base URL for CloudConnexa API v1 endpoints. func (c *Client) GetV1Url() string { return c.BaseURL + "/api/v1" } diff --git a/cloudconnexa/cloudconnexa_test.go b/cloudconnexa/cloudconnexa_test.go index 2f4c62d..9e098a8 100644 --- a/cloudconnexa/cloudconnexa_test.go +++ b/cloudconnexa/cloudconnexa_test.go @@ -11,6 +11,8 @@ import ( "golang.org/x/time/rate" ) +// setupMockServer creates a test HTTP server that simulates the CloudConnexa API endpoints +// for testing purposes. It handles token authentication and basic endpoint responses. func setupMockServer() *httptest.Server { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { @@ -36,6 +38,9 @@ func setupMockServer() *httptest.Server { return server } +// TestNewClient tests the creation of a new CloudConnexa client with various credential combinations. +// It verifies that the client is properly initialized with valid credentials and returns +// appropriate errors for invalid credentials. func TestNewClient(t *testing.T) { server := setupMockServer() defer server.Close() @@ -66,6 +71,9 @@ func TestNewClient(t *testing.T) { } } +// TestDoRequest tests the DoRequest method of the CloudConnexa client. +// It verifies that the client correctly handles various HTTP requests and responses, +// including valid requests, invalid endpoints, and incorrect HTTP methods. func TestDoRequest(t *testing.T) { server := setupMockServer() defer server.Close() diff --git a/cloudconnexa/dns_records.go b/cloudconnexa/dns_records.go index 7808b27..b988796 100644 --- a/cloudconnexa/dns_records.go +++ b/cloudconnexa/dns_records.go @@ -9,9 +9,11 @@ import ( ) var ( + // ErrDNSRecordNotFound is returned when a DNS record is not found. ErrDNSRecordNotFound = errors.New("dns record not found") ) +// DNSRecord represents a DNS record in CloudConnexa. type DNSRecord struct { ID string `json:"id"` Domain string `json:"domain"` @@ -20,6 +22,7 @@ type DNSRecord struct { IPV6Addresses []string `json:"ipv6Addresses"` } +// DNSRecordPageResponse represents a paginated response of DNS records. type DNSRecordPageResponse struct { Content []DNSRecord `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -30,8 +33,10 @@ type DNSRecordPageResponse struct { TotalPages int `json:"totalPages"` } +// DNSRecordsService provides methods for managing DNS records. type DNSRecordsService service +// GetByPage retrieves DNS records using pagination. func (c *DNSRecordsService) GetByPage(page int, pageSize int) (DNSRecordPageResponse, error) { endpoint := fmt.Sprintf("%s/dns-records?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -52,6 +57,7 @@ func (c *DNSRecordsService) GetByPage(page int, pageSize int) (DNSRecordPageResp return response, nil } +// GetDNSRecord retrieves a specific DNS record by ID. func (c *DNSRecordsService) GetDNSRecord(recordID string) (*DNSRecord, error) { pageSize := 10 page := 0 @@ -76,6 +82,7 @@ func (c *DNSRecordsService) GetDNSRecord(recordID string) (*DNSRecord, error) { return nil, ErrDNSRecordNotFound } +// Create creates a new DNS record. func (c *DNSRecordsService) Create(record DNSRecord) (*DNSRecord, error) { recordJSON, err := json.Marshal(record) if err != nil { @@ -100,6 +107,7 @@ func (c *DNSRecordsService) Create(record DNSRecord) (*DNSRecord, error) { return &d, nil } +// Update updates an existing DNS record. func (c *DNSRecordsService) Update(record DNSRecord) error { recordJSON, err := json.Marshal(record) if err != nil { @@ -115,6 +123,7 @@ func (c *DNSRecordsService) Update(record DNSRecord) error { return err } +// Delete deletes a DNS record by ID. func (c *DNSRecordsService) Delete(recordID string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/dns-records/%s", c.client.GetV1Url(), recordID), nil) if err != nil { diff --git a/cloudconnexa/errors.go b/cloudconnexa/errors.go index b57e489..dbcf649 100644 --- a/cloudconnexa/errors.go +++ b/cloudconnexa/errors.go @@ -2,4 +2,5 @@ package cloudconnexa import "errors" +// ErrCredentialsRequired is returned when client ID or client secret is missing. var ErrCredentialsRequired = errors.New("both client_id and client_secret credentials must be specified") diff --git a/cloudconnexa/host_applications.go b/cloudconnexa/host_applications.go index 30be18f..eabef51 100644 --- a/cloudconnexa/host_applications.go +++ b/cloudconnexa/host_applications.go @@ -7,22 +7,26 @@ import ( "net/http" ) +// ApplicationRoute represents a route configuration for an application. type ApplicationRoute struct { Value string `json:"value"` AllowEmbeddedIP bool `json:"allowEmbeddedIp"` } +// CustomApplicationType represents a custom application type configuration. type CustomApplicationType struct { IcmpType []Range `json:"icmpType"` Port []Range `json:"port"` Protocol string `json:"protocol"` } +// ApplicationConfig represents the configuration for an application including custom service types and predefined service types. type ApplicationConfig struct { CustomServiceTypes []*CustomApplicationType `json:"customServiceTypes"` ServiceTypes []string `json:"serviceTypes"` } +// Application represents a host application with its configuration and routing information. type Application struct { Name string `json:"name"` Description string `json:"description"` @@ -33,11 +37,15 @@ type Application struct { Config *ApplicationConfig `json:"config"` } +// ApplicationResponse represents the response structure for application operations, +// extending the base Application with additional route information. type ApplicationResponse struct { Application Routes []*Route `json:"routes"` } +// ApplicationPageResponse represents a paginated response from the CloudConnexa API +// containing a list of applications and pagination metadata. type ApplicationPageResponse struct { Content []ApplicationResponse `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -48,8 +56,11 @@ type ApplicationPageResponse struct { TotalPages int `json:"totalPages"` } +// HostApplicationsService handles communication with the CloudConnexa API for host application operations. type HostApplicationsService service +// GetApplicationsByPage retrieves a paginated list of host applications from the CloudConnexa API. +// It returns the applications for the specified page and page size. func (c *HostApplicationsService) GetApplicationsByPage(page int, pageSize int) (ApplicationPageResponse, error) { endpoint := fmt.Sprintf("%s/hosts/applications?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -70,6 +81,8 @@ func (c *HostApplicationsService) GetApplicationsByPage(page int, pageSize int) return response, nil } +// List retrieves all host applications from the CloudConnexa API. +// It handles pagination internally and returns a complete list of applications. func (c *HostApplicationsService) List() ([]ApplicationResponse, error) { var allApplications []ApplicationResponse page := 0 @@ -90,6 +103,7 @@ func (c *HostApplicationsService) List() ([]ApplicationResponse, error) { return allApplications, nil } +// Get retrieves a specific host application by its ID. func (c *HostApplicationsService) Get(id string) (*ApplicationResponse, error) { endpoint := fmt.Sprintf("%s/hosts/applications/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -110,6 +124,7 @@ func (c *HostApplicationsService) Get(id string) (*ApplicationResponse, error) { return &application, nil } +// Create creates a new host application. func (c *HostApplicationsService) Create(application *Application) (*ApplicationResponse, error) { applicationJSON, err := json.Marshal(application) if err != nil { @@ -136,6 +151,7 @@ func (c *HostApplicationsService) Create(application *Application) (*Application return &s, nil } +// Update updates an existing host application by its ID. func (c *HostApplicationsService) Update(id string, application *Application) (*ApplicationResponse, error) { applicationJSON, err := json.Marshal(application) if err != nil { @@ -162,6 +178,7 @@ func (c *HostApplicationsService) Update(id string, application *Application) (* return &s, nil } +// Delete removes a host application by its ID. func (c *HostApplicationsService) Delete(id string) error { endpoint := fmt.Sprintf("%s/hosts/applications/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodDelete, endpoint, nil) diff --git a/cloudconnexa/host_connectors.go b/cloudconnexa/host_connectors.go index 7f819c4..a8b1d64 100644 --- a/cloudconnexa/host_connectors.go +++ b/cloudconnexa/host_connectors.go @@ -5,10 +5,9 @@ import ( "encoding/json" "fmt" "net/http" - "net/url" - "strconv" ) +// HostConnector represents a host connector in CloudConnexa. type HostConnector struct { ID string `json:"id,omitempty"` Name string `json:"name"` @@ -22,6 +21,7 @@ type HostConnector struct { ConnectionStatus string `json:"connectionStatus"` } +// HostConnectorPageResponse represents a paginated response of host connectors. type HostConnectorPageResponse struct { Content []HostConnector `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -32,21 +32,23 @@ type HostConnectorPageResponse struct { TotalPages int `json:"totalPages"` } +// HostConnectorsService provides methods for managing host connectors. type HostConnectorsService service +// GetByPage retrieves host connectors using pagination. func (c *HostConnectorsService) GetByPage(page int, pageSize int) (HostConnectorPageResponse, error) { return c.GetByPageAndHostID(page, pageSize, "") } +// GetByPageAndHostID retrieves host connectors using pagination, optionally filtered by host ID. func (c *HostConnectorsService) GetByPageAndHostID(page int, pageSize int, hostID string) (HostConnectorPageResponse, error) { - params := url.Values{} - params.Add("page", strconv.Itoa(page)) - params.Add("size", strconv.Itoa(pageSize)) + var endpoint string if hostID != "" { - params.Add("hostId", hostID) + endpoint = fmt.Sprintf("%s/hosts/connectors?hostId=%s&page=%d&size=%d", c.client.GetV1Url(), hostID, page, pageSize) + } else { + endpoint = fmt.Sprintf("%s/hosts/connectors?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) } - endpoint := fmt.Sprintf("%s/hosts/connectors?%s", c.client.GetV1Url(), params.Encode()) req, err := http.NewRequest(http.MethodGet, endpoint, nil) if err != nil { return HostConnectorPageResponse{}, err @@ -65,6 +67,7 @@ func (c *HostConnectorsService) GetByPageAndHostID(page int, pageSize int, hostI return response, nil } +// Update updates an existing host connector. func (c *HostConnectorsService) Update(connector HostConnector) (*HostConnector, error) { connectorJSON, err := json.Marshal(connector) if err != nil { @@ -89,10 +92,12 @@ func (c *HostConnectorsService) Update(connector HostConnector) (*HostConnector, return &conn, nil } +// List retrieves all host connectors. func (c *HostConnectorsService) List() ([]HostConnector, error) { return c.ListByHostID("") } +// ListByHostID retrieves all host connectors for a specific host ID. func (c *HostConnectorsService) ListByHostID(hostID string) ([]HostConnector, error) { var allConnectors []HostConnector page := 0 @@ -114,6 +119,7 @@ func (c *HostConnectorsService) ListByHostID(hostID string) ([]HostConnector, er return allConnectors, nil } +// GetByID retrieves a specific host connector by ID. func (c *HostConnectorsService) GetByID(id string) (*HostConnector, error) { endpoint := fmt.Sprintf("%s/hosts/connectors/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -134,6 +140,7 @@ func (c *HostConnectorsService) GetByID(id string) (*HostConnector, error) { return &connector, nil } +// GetProfile retrieves the profile configuration for a host connector. func (c *HostConnectorsService) GetProfile(id string) (string, error) { req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/hosts/connectors/%s/profile", c.client.GetV1Url(), id), nil) if err != nil { @@ -147,6 +154,7 @@ func (c *HostConnectorsService) GetProfile(id string) (string, error) { return string(body), nil } +// GetToken retrieves an encrypted token for a host connector. func (c *HostConnectorsService) GetToken(id string) (string, error) { req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/hosts/connectors/%s/profile/encrypt", c.client.GetV1Url(), id), nil) if err != nil { @@ -160,6 +168,7 @@ func (c *HostConnectorsService) GetToken(id string) (string, error) { return string(body), nil } +// Create creates a new host connector for the specified host. func (c *HostConnectorsService) Create(connector HostConnector, hostID string) (*HostConnector, error) { connectorJSON, err := json.Marshal(connector) if err != nil { @@ -184,6 +193,7 @@ func (c *HostConnectorsService) Create(connector HostConnector, hostID string) ( return &conn, nil } +// Delete deletes a host connector by ID. func (c *HostConnectorsService) Delete(connectorID string, hostID string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/hosts/connectors/%s?hostId=%s", c.client.GetV1Url(), connectorID, hostID), nil) if err != nil { diff --git a/cloudconnexa/host_ip_services.go b/cloudconnexa/host_ip_services.go index 84ec44b..cc557e2 100644 --- a/cloudconnexa/host_ip_services.go +++ b/cloudconnexa/host_ip_services.go @@ -7,28 +7,33 @@ import ( "net/http" ) +// Range represents a range of values with lower and upper bounds, or a single value. type Range struct { LowerValue int `json:"lowerValue"` UpperValue int `json:"upperValue"` Value int `json:"value,omitempty"` } +// CustomIPServiceType represents a custom IP service type configuration with ICMP type, port ranges, and protocol. type CustomIPServiceType struct { IcmpType []Range `json:"icmpType"` Port []Range `json:"port"` Protocol string `json:"protocol"` } +// IPServiceRoute represents a route configuration for an IP service. type IPServiceRoute struct { Description string `json:"description"` Value string `json:"value"` } +// IPServiceConfig represents the configuration for an IP service including custom service types and predefined service types. type IPServiceConfig struct { CustomServiceTypes []*CustomIPServiceType `json:"customServiceTypes"` ServiceTypes []string `json:"serviceTypes"` } +// IPService represents an IP service with its configuration and routing information. type IPService struct { Name string `json:"name"` Description string `json:"description"` @@ -40,11 +45,15 @@ type IPService struct { Config *IPServiceConfig `json:"config"` } +// IPServiceResponse represents the response structure for IP service operations, +// extending the base IPService with additional route information. type IPServiceResponse struct { IPService Routes []*Route `json:"routes"` } +// IPServicePageResponse represents a paginated response from the CloudConnexa API +// containing a list of IP services and pagination metadata. type IPServicePageResponse struct { Content []IPServiceResponse `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -55,8 +64,10 @@ type IPServicePageResponse struct { TotalPages int `json:"totalPages"` } +// HostIPServicesService provides methods for managing IP services. type HostIPServicesService service +// GetIPByPage retrieves IP services using pagination. func (c *HostIPServicesService) GetIPByPage(page int, pageSize int) (IPServicePageResponse, error) { endpoint := fmt.Sprintf("%s/hosts/ip-services?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -77,6 +88,7 @@ func (c *HostIPServicesService) GetIPByPage(page int, pageSize int) (IPServicePa return response, nil } +// List retrieves all IP services by paginating through all available pages. func (c *HostIPServicesService) List() ([]IPServiceResponse, error) { var allIPServices []IPServiceResponse page := 0 @@ -97,6 +109,7 @@ func (c *HostIPServicesService) List() ([]IPServiceResponse, error) { return allIPServices, nil } +// Get retrieves a specific IP service by its ID. func (c *HostIPServicesService) Get(id string) (*IPServiceResponse, error) { endpoint := fmt.Sprintf("%s/hosts/ip-services/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -117,6 +130,7 @@ func (c *HostIPServicesService) Get(id string) (*IPServiceResponse, error) { return &service, nil } +// Create creates a new IP service. func (c *HostIPServicesService) Create(ipService *IPService) (*IPServiceResponse, error) { ipServiceJSON, err := json.Marshal(ipService) if err != nil { @@ -143,6 +157,7 @@ func (c *HostIPServicesService) Create(ipService *IPService) (*IPServiceResponse return &s, nil } +// Update updates an existing IP service by its ID. func (c *HostIPServicesService) Update(id string, service *IPService) (*IPServiceResponse, error) { serviceJSON, err := json.Marshal(service) if err != nil { @@ -169,6 +184,7 @@ func (c *HostIPServicesService) Update(id string, service *IPService) (*IPServic return &s, nil } +// Delete removes an IP service by its ID. func (c *HostIPServicesService) Delete(ipServiceID string) error { endpoint := fmt.Sprintf("%s/hosts/ip-services/%s", c.client.GetV1Url(), ipServiceID) req, err := http.NewRequest(http.MethodDelete, endpoint, nil) diff --git a/cloudconnexa/hosts.go b/cloudconnexa/hosts.go index d48b563..d173dcb 100644 --- a/cloudconnexa/hosts.go +++ b/cloudconnexa/hosts.go @@ -7,6 +7,7 @@ import ( "net/http" ) +// Host represents a host in CloudConnexa. type Host struct { ID string `json:"id,omitempty"` Name string `json:"name"` @@ -17,6 +18,7 @@ type Host struct { Connectors []HostConnector `json:"connectors"` } +// HostPageResponse represents a paginated response of hosts. type HostPageResponse struct { Content []Host `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -27,8 +29,10 @@ type HostPageResponse struct { TotalPages int `json:"totalPages"` } +// HostsService provides methods for managing hosts. type HostsService service +// GetHostsByPage retrieves hosts using pagination. func (c *HostsService) GetHostsByPage(page int, size int) (HostPageResponse, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/hosts?page=%d&size=%d", c.client.GetV1Url(), page, size), nil) if err != nil { @@ -48,6 +52,7 @@ func (c *HostsService) GetHostsByPage(page int, size int) (HostPageResponse, err return response, nil } +// List retrieves all hosts. func (c *HostsService) List() ([]Host, error) { var allHosts []Host pageSize := 10 @@ -69,6 +74,7 @@ func (c *HostsService) List() ([]Host, error) { return allHosts, nil } +// Get retrieves a specific host by ID. func (c *HostsService) Get(id string) (*Host, error) { endpoint := fmt.Sprintf("%s/hosts/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -89,6 +95,7 @@ func (c *HostsService) Get(id string) (*Host, error) { return &host, nil } +// Create creates a new host. func (c *HostsService) Create(host Host) (*Host, error) { hostJSON, err := json.Marshal(host) if err != nil { @@ -113,6 +120,7 @@ func (c *HostsService) Create(host Host) (*Host, error) { return &h, nil } +// Update updates an existing host. func (c *HostsService) Update(host Host) error { hostJSON, err := json.Marshal(host) if err != nil { @@ -128,6 +136,7 @@ func (c *HostsService) Update(host Host) error { return err } +// Delete deletes a host by ID. func (c *HostsService) Delete(hostID string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/hosts/%s", c.client.GetV1Url(), hostID), nil) if err != nil { diff --git a/cloudconnexa/location_contexts.go b/cloudconnexa/location_contexts.go index 9e3b1d9..68d5843 100644 --- a/cloudconnexa/location_contexts.go +++ b/cloudconnexa/location_contexts.go @@ -7,6 +7,7 @@ import ( "net/http" ) +// LocationContext represents a location context in CloudConnexa with its associated checks and user groups. type LocationContext struct { ID string `json:"id"` Name string `json:"name"` @@ -17,25 +18,31 @@ type LocationContext struct { DefaultCheck *DefaultCheck `json:"defaultCheck"` } +// IPCheck represents the IP-based access control configuration. type IPCheck struct { Allowed bool `json:"allowed"` Ips []IP `json:"ips"` } +// CountryCheck represents the country-based access control configuration. type CountryCheck struct { Allowed bool `json:"allowed"` Countries []string `json:"countries"` } +// DefaultCheck represents the default access control configuration. type DefaultCheck struct { Allowed bool `json:"allowed"` } +// IP represents an IP address with its description. type IP struct { IP string `json:"ip"` Description string `json:"description"` } +// LocationContextPageResponse represents a paginated response from the CloudConnexa API +// containing a list of location contexts and pagination metadata. type LocationContextPageResponse struct { Content []LocationContext `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -46,8 +53,10 @@ type LocationContextPageResponse struct { TotalPages int `json:"totalPages"` } +// LocationContextsService provides methods for managing location contexts. type LocationContextsService service +// GetLocationContextByPage retrieves location contexts using pagination. func (c *LocationContextsService) GetLocationContextByPage(page int, pageSize int) (LocationContextPageResponse, error) { endpoint := fmt.Sprintf("%s/location-contexts?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -68,6 +77,7 @@ func (c *LocationContextsService) GetLocationContextByPage(page int, pageSize in return response, nil } +// List retrieves all location contexts by paginating through all available pages. func (c *LocationContextsService) List() ([]LocationContext, error) { var allLocationContexts []LocationContext page := 0 @@ -88,6 +98,7 @@ func (c *LocationContextsService) List() ([]LocationContext, error) { return allLocationContexts, nil } +// Get retrieves a specific location context by its ID. func (c *LocationContextsService) Get(id string) (*LocationContext, error) { endpoint := fmt.Sprintf("%s/location-contexts/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -108,6 +119,7 @@ func (c *LocationContextsService) Get(id string) (*LocationContext, error) { return &locationContext, nil } +// Create creates a new location context. func (c *LocationContextsService) Create(locationContext *LocationContext) (*LocationContext, error) { locationContextJSON, err := json.Marshal(locationContext) if err != nil { @@ -133,6 +145,7 @@ func (c *LocationContextsService) Create(locationContext *LocationContext) (*Loc return &s, nil } +// Update updates an existing location context by its ID. func (c *LocationContextsService) Update(id string, locationContext *LocationContext) (*LocationContext, error) { locationContextJSON, err := json.Marshal(locationContext) if err != nil { @@ -158,6 +171,7 @@ func (c *LocationContextsService) Update(id string, locationContext *LocationCon return &s, nil } +// Delete removes a location context by its ID. func (c *LocationContextsService) Delete(id string) error { endpoint := fmt.Sprintf("%s/location-contexts/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodDelete, endpoint, nil) diff --git a/cloudconnexa/network_applications.go b/cloudconnexa/network_applications.go index 1962c68..12a6b6b 100644 --- a/cloudconnexa/network_applications.go +++ b/cloudconnexa/network_applications.go @@ -7,8 +7,10 @@ import ( "net/http" ) +// NetworkApplicationsService provides methods for managing network applications. type NetworkApplicationsService service +// GetApplicationsByPage retrieves network applications using pagination. func (c *NetworkApplicationsService) GetApplicationsByPage(page int, pageSize int) (ApplicationPageResponse, error) { endpoint := fmt.Sprintf("%s/networks/applications?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -29,6 +31,7 @@ func (c *NetworkApplicationsService) GetApplicationsByPage(page int, pageSize in return response, nil } +// List retrieves all network applications by paginating through all available pages. func (c *NetworkApplicationsService) List() ([]ApplicationResponse, error) { var allApplications []ApplicationResponse page := 0 @@ -49,6 +52,7 @@ func (c *NetworkApplicationsService) List() ([]ApplicationResponse, error) { return allApplications, nil } +// Get retrieves a specific network application by its ID. func (c *NetworkApplicationsService) Get(id string) (*ApplicationResponse, error) { endpoint := fmt.Sprintf("%s/networks/applications/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -69,6 +73,7 @@ func (c *NetworkApplicationsService) Get(id string) (*ApplicationResponse, error return &application, nil } +// Create creates a new network application. func (c *NetworkApplicationsService) Create(application *Application) (*ApplicationResponse, error) { applicationJSON, err := json.Marshal(application) if err != nil { @@ -95,6 +100,7 @@ func (c *NetworkApplicationsService) Create(application *Application) (*Applicat return &s, nil } +// Update updates an existing network application by its ID. func (c *NetworkApplicationsService) Update(id string, application *Application) (*ApplicationResponse, error) { applicationJSON, err := json.Marshal(application) if err != nil { @@ -121,6 +127,7 @@ func (c *NetworkApplicationsService) Update(id string, application *Application) return &s, nil } +// Delete removes a network application by its ID. func (c *NetworkApplicationsService) Delete(id string) error { endpoint := fmt.Sprintf("%s/networks/applications/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodDelete, endpoint, nil) diff --git a/cloudconnexa/network_connectors.go b/cloudconnexa/network_connectors.go index 24624d8..746fb49 100644 --- a/cloudconnexa/network_connectors.go +++ b/cloudconnexa/network_connectors.go @@ -9,6 +9,7 @@ import ( "strconv" ) +// NetworkConnector represents a network connector configuration. type NetworkConnector struct { ID string `json:"id,omitempty"` Name string `json:"name"` @@ -22,6 +23,7 @@ type NetworkConnector struct { ConnectionStatus string `json:"connectionStatus"` } +// NetworkConnectorPageResponse represents a paginated response of network connectors. type NetworkConnectorPageResponse struct { Content []NetworkConnector `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -32,12 +34,15 @@ type NetworkConnectorPageResponse struct { TotalPages int `json:"totalPages"` } +// NetworkConnectorsService provides methods for managing network connectors. type NetworkConnectorsService service +// GetByPage retrieves network connectors using pagination. func (c *NetworkConnectorsService) GetByPage(page int, pageSize int) (NetworkConnectorPageResponse, error) { return c.GetByPageAndNetworkID(page, pageSize, "") } +// GetByPageAndNetworkID retrieves network connectors for a specific network using pagination. func (c *NetworkConnectorsService) GetByPageAndNetworkID(page int, pageSize int, networkID string) (NetworkConnectorPageResponse, error) { params := url.Values{} params.Add("page", strconv.Itoa(page)) @@ -65,6 +70,7 @@ func (c *NetworkConnectorsService) GetByPageAndNetworkID(page int, pageSize int, return response, nil } +// Update updates an existing network connector. func (c *NetworkConnectorsService) Update(connector NetworkConnector) (*NetworkConnector, error) { connectorJSON, err := json.Marshal(connector) if err != nil { @@ -89,6 +95,7 @@ func (c *NetworkConnectorsService) Update(connector NetworkConnector) (*NetworkC return &conn, nil } +// List retrieves all network connectors by paginating through all available pages. func (c *NetworkConnectorsService) List() ([]NetworkConnector, error) { var allConnectors []NetworkConnector page := 0 @@ -110,6 +117,7 @@ func (c *NetworkConnectorsService) List() ([]NetworkConnector, error) { return allConnectors, nil } +// ListByNetworkID retrieves all network connectors for a specific network by paginating through all available pages. func (c *NetworkConnectorsService) ListByNetworkID(networkID string) ([]NetworkConnector, error) { var allConnectors []NetworkConnector page := 0 @@ -131,6 +139,7 @@ func (c *NetworkConnectorsService) ListByNetworkID(networkID string) ([]NetworkC return allConnectors, nil } +// GetByID retrieves a specific network connector by its ID. func (c *NetworkConnectorsService) GetByID(id string) (*NetworkConnector, error) { endpoint := fmt.Sprintf("%s/networks/connectors/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -151,6 +160,7 @@ func (c *NetworkConnectorsService) GetByID(id string) (*NetworkConnector, error) return &connector, nil } +// GetProfile retrieves the profile configuration for a specific network connector. func (c *NetworkConnectorsService) GetProfile(id string) (string, error) { req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/networks/connectors/%s/profile", c.client.GetV1Url(), id), nil) if err != nil { @@ -164,6 +174,7 @@ func (c *NetworkConnectorsService) GetProfile(id string) (string, error) { return string(body), nil } +// GetToken retrieves an encrypted token for a specific network connector. func (c *NetworkConnectorsService) GetToken(id string) (string, error) { req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/networks/connectors/%s/profile/encrypt", c.client.GetV1Url(), id), nil) if err != nil { @@ -177,6 +188,7 @@ func (c *NetworkConnectorsService) GetToken(id string) (string, error) { return string(body), nil } +// Create creates a new network connector. func (c *NetworkConnectorsService) Create(connector NetworkConnector, networkID string) (*NetworkConnector, error) { connectorJSON, err := json.Marshal(connector) if err != nil { @@ -201,6 +213,7 @@ func (c *NetworkConnectorsService) Create(connector NetworkConnector, networkID return &conn, nil } +// Delete removes a network connector by its ID and network ID. func (c *NetworkConnectorsService) Delete(connectorID string, networkID string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/networks/connectors/%s?networkId=%s", c.client.GetV1Url(), connectorID, networkID), nil) if err != nil { diff --git a/cloudconnexa/network_ip_services.go b/cloudconnexa/network_ip_services.go index d7b0337..2295adc 100644 --- a/cloudconnexa/network_ip_services.go +++ b/cloudconnexa/network_ip_services.go @@ -7,8 +7,13 @@ import ( "net/http" ) +// NetworkIPServicesService handles communication with the CloudConnexa IP Services API type NetworkIPServicesService service +// GetIPByPage retrieves a page of IP services with pagination +// page: The page number to retrieve +// pageSize: The number of items per page +// Returns a page of IP services and any error that occurred func (c *NetworkIPServicesService) GetIPByPage(page int, pageSize int) (IPServicePageResponse, error) { endpoint := fmt.Sprintf("%s/networks/ip-services?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -29,6 +34,8 @@ func (c *NetworkIPServicesService) GetIPByPage(page int, pageSize int) (IPServic return response, nil } +// List retrieves all IP services by paginating through all available pages +// Returns a slice of IP services and any error that occurred func (c *NetworkIPServicesService) List() ([]IPServiceResponse, error) { var allIPServices []IPServiceResponse page := 0 @@ -49,6 +56,9 @@ func (c *NetworkIPServicesService) List() ([]IPServiceResponse, error) { return allIPServices, nil } +// Get retrieves a specific IP service by its ID +// id: The ID of the IP service to retrieve +// Returns the IP service and any error that occurred func (c *NetworkIPServicesService) Get(id string) (*IPServiceResponse, error) { endpoint := fmt.Sprintf("%s/networks/ip-services/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -69,6 +79,9 @@ func (c *NetworkIPServicesService) Get(id string) (*IPServiceResponse, error) { return &service, nil } +// Create creates a new IP service +// ipService: The IP service configuration to create +// Returns the created IP service and any error that occurred func (c *NetworkIPServicesService) Create(ipService *IPService) (*IPServiceResponse, error) { ipServiceJSON, err := json.Marshal(ipService) if err != nil { @@ -95,6 +108,10 @@ func (c *NetworkIPServicesService) Create(ipService *IPService) (*IPServiceRespo return &s, nil } +// Update updates an existing IP service +// id: The ID of the IP service to update +// service: The updated IP service configuration +// Returns the updated IP service and any error that occurred func (c *NetworkIPServicesService) Update(id string, service *IPService) (*IPServiceResponse, error) { serviceJSON, err := json.Marshal(service) if err != nil { @@ -121,6 +138,9 @@ func (c *NetworkIPServicesService) Update(id string, service *IPService) (*IPSer return &s, nil } +// Delete removes an IP service by its ID +// IPServiceID: The ID of the IP service to delete +// Returns any error that occurred during deletion func (c *NetworkIPServicesService) Delete(IPServiceID string) error { endpoint := fmt.Sprintf("%s/networks/ip-services/%s", c.client.GetV1Url(), IPServiceID) req, err := http.NewRequest(http.MethodDelete, endpoint, nil) diff --git a/cloudconnexa/networks.go b/cloudconnexa/networks.go index 3435a80..b4cd17b 100644 --- a/cloudconnexa/networks.go +++ b/cloudconnexa/networks.go @@ -8,11 +8,15 @@ import ( ) const ( - InternetAccessSplitTunnelOn = "SPLIT_TUNNEL_ON" - InternetAccessSplitTunnelOff = "SPLIT_TUNNEL_OFF" + // InternetAccessSplitTunnelOn enables split tunneling for internet access. + InternetAccessSplitTunnelOn = "SPLIT_TUNNEL_ON" + // InternetAccessSplitTunnelOff disables split tunneling for internet access. + InternetAccessSplitTunnelOff = "SPLIT_TUNNEL_OFF" + // InternetAccessRestrictedInternet restricts internet access. InternetAccessRestrictedInternet = "RESTRICTED_INTERNET" ) +// Network represents a network in CloudConnexa. type Network struct { Connectors []NetworkConnector `json:"connectors"` Description string `json:"description"` @@ -25,6 +29,7 @@ type Network struct { NetworkItemID string `json:"NetworkItemID"` } +// NetworkPageResponse represents a paginated response of networks. type NetworkPageResponse struct { Content []Network `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -35,8 +40,13 @@ type NetworkPageResponse struct { TotalPages int `json:"totalPages"` } +// NetworksService provides methods for managing networks. type NetworksService service +// GetByPage retrieves networks using pagination. +// page: The page number to retrieve +// size: The number of items per page +// Returns a NetworkPageResponse containing the networks and pagination information func (c *NetworksService) GetByPage(page int, size int) (NetworkPageResponse, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/networks?page=%d&size=%d", c.client.GetV1Url(), page, size), nil) if err != nil { @@ -57,6 +67,8 @@ func (c *NetworksService) GetByPage(page int, size int) (NetworkPageResponse, er return response, nil } +// List retrieves all networks by paginating through all available pages. +// Returns a slice of all networks and any error that occurred func (c *NetworksService) List() ([]Network, error) { var allNetworks []Network pageSize := 10 @@ -78,6 +90,9 @@ func (c *NetworksService) List() ([]Network, error) { return allNetworks, nil } +// Get retrieves a specific network by its ID. +// id: The ID of the network to retrieve +// Returns the network and any error that occurred func (c *NetworksService) Get(id string) (*Network, error) { endpoint := fmt.Sprintf("%s/networks/%s", c.client.GetV1Url(), id) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -98,6 +113,9 @@ func (c *NetworksService) Get(id string) (*Network, error) { return &network, nil } +// Create creates a new network. +// network: The network configuration to create +// Returns the created network and any error that occurred func (c *NetworksService) Create(network Network) (*Network, error) { networkJSON, err := json.Marshal(network) if err != nil { @@ -122,6 +140,9 @@ func (c *NetworksService) Create(network Network) (*Network, error) { return &n, nil } +// Update updates an existing network. +// network: The updated network configuration +// Returns any error that occurred during the update func (c *NetworksService) Update(network Network) error { networkJSON, err := json.Marshal(network) if err != nil { @@ -137,6 +158,9 @@ func (c *NetworksService) Update(network Network) error { return err } +// Delete removes a network by its ID. +// networkID: The ID of the network to delete +// Returns any error that occurred during deletion func (c *NetworksService) Delete(networkID string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/networks/%s", c.client.GetV1Url(), networkID), nil) if err != nil { diff --git a/cloudconnexa/routes.go b/cloudconnexa/routes.go index 7d2641e..fc9992b 100644 --- a/cloudconnexa/routes.go +++ b/cloudconnexa/routes.go @@ -7,6 +7,7 @@ import ( "net/http" ) +// Route represents a network route configuration type Route struct { ID string `json:"id,omitempty"` Type string `json:"type,omitempty"` @@ -18,6 +19,7 @@ type Route struct { AllowEmbeddedIP bool `json:"allowEmbeddedIp,omitempty"` } +// RoutePageResponse represents a paginated response of network routes type RoutePageResponse struct { Success bool `json:"success"` Content []Route `json:"content"` @@ -28,8 +30,14 @@ type RoutePageResponse struct { Size int `json:"size"` } +// RoutesService provides methods for managing network routes type RoutesService service +// GetByPage retrieves network routes using pagination +// networkID: The ID of the network to get routes for +// page: The page number to retrieve +// size: The number of items per page +// Returns a page of routes and any error that occurred func (c *RoutesService) GetByPage(networkID string, page int, size int) (RoutePageResponse, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/networks/routes?networkId=%s&page=%d&size=%d", c.client.GetV1Url(), networkID, page, size), nil) if err != nil { @@ -49,6 +57,9 @@ func (c *RoutesService) GetByPage(networkID string, page int, size int) (RoutePa return response, nil } +// List retrieves all routes for a network by paginating through all available pages +// networkID: The ID of the network to get routes for +// Returns a slice of routes and any error that occurred func (c *RoutesService) List(networkID string) ([]Route, error) { var allRoutes []Route pageSize := 10 @@ -70,6 +81,10 @@ func (c *RoutesService) List(networkID string) ([]Route, error) { return allRoutes, nil } +// GetNetworkRoute retrieves a specific route from a network +// networkID: The ID of the network containing the route +// routeID: The ID of the route to retrieve +// Returns the route and any error that occurred func (c *RoutesService) GetNetworkRoute(networkID string, routeID string) (*Route, error) { routes, err := c.List(networkID) if err != nil { @@ -84,6 +99,9 @@ func (c *RoutesService) GetNetworkRoute(networkID string, routeID string) (*Rout return nil, nil } +// Get retrieves a specific route by searching through all networks +// routeID: The ID of the route to retrieve +// Returns the route and any error that occurred func (c *RoutesService) Get(routeID string) (*Route, error) { networks, err := c.client.Networks.List() if err != nil { @@ -104,6 +122,10 @@ func (c *RoutesService) Get(routeID string) (*Route, error) { return nil, nil } +// Create creates a new route in a network +// networkID: The ID of the network to create the route in +// route: The route configuration to create +// Returns the created route and any error that occurred func (c *RoutesService) Create(networkID string, route Route) (*Route, error) { type newRoute struct { Description string `json:"description"` @@ -140,6 +162,9 @@ func (c *RoutesService) Create(networkID string, route Route) (*Route, error) { return &r, nil } +// Update updates an existing route +// route: The updated route configuration +// Returns any error that occurred during the update func (c *RoutesService) Update(route Route) error { type updatedRoute struct { Description string `json:"description"` @@ -168,6 +193,9 @@ func (c *RoutesService) Update(route Route) error { return err } +// Delete removes a route by its ID +// id: The ID of the route to delete +// Returns any error that occurred during deletion func (c *RoutesService) Delete(id string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/networks/routes/%s", c.client.GetV1Url(), id), nil) if err != nil { diff --git a/cloudconnexa/user_groups.go b/cloudconnexa/user_groups.go index 07458d5..ff362c9 100644 --- a/cloudconnexa/user_groups.go +++ b/cloudconnexa/user_groups.go @@ -9,9 +9,11 @@ import ( ) var ( + // ErrUserGroupNotFound is returned when a user group cannot be found ErrUserGroupNotFound = errors.New("user group not found") ) +// UserGroupPageResponse represents a paginated response of user groups type UserGroupPageResponse struct { Content []UserGroup `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -22,6 +24,7 @@ type UserGroupPageResponse struct { TotalPages int `json:"totalPages"` } +// UserGroup represents a user group configuration type UserGroup struct { ConnectAuth string `json:"connectAuth"` ID string `json:"id"` @@ -33,8 +36,13 @@ type UserGroup struct { AllRegionsIncluded bool `json:"allRegionsIncluded"` } +// UserGroupsService provides methods for managing user groups type UserGroupsService service +// GetByPage retrieves user groups using pagination +// page: The page number to retrieve +// pageSize: The number of items per page +// Returns a page of user groups and any error that occurred func (c *UserGroupsService) GetByPage(page int, pageSize int) (UserGroupPageResponse, error) { endpoint := fmt.Sprintf("%s/user-groups?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -55,6 +63,8 @@ func (c *UserGroupsService) GetByPage(page int, pageSize int) (UserGroupPageResp return response, nil } +// List retrieves all user groups by paginating through all available pages +// Returns a slice of user groups and any error that occurred func (c *UserGroupsService) List() ([]UserGroup, error) { var allUserGroups []UserGroup pageSize := 10 @@ -76,6 +86,9 @@ func (c *UserGroupsService) List() ([]UserGroup, error) { return allUserGroups, nil } +// GetByName retrieves a user group by its name +// name: The name of the user group to retrieve +// Returns the user group and any error that occurred func (c *UserGroupsService) GetByName(name string) (*UserGroup, error) { userGroups, err := c.List() if err != nil { @@ -90,6 +103,9 @@ func (c *UserGroupsService) GetByName(name string) (*UserGroup, error) { return nil, ErrUserGroupNotFound } +// Get retrieves a user group by its ID +// id: The ID of the user group to retrieve +// Returns the user group and any error that occurred func (c *UserGroupsService) Get(id string) (*UserGroup, error) { userGroups, err := c.List() if err != nil { @@ -104,6 +120,9 @@ func (c *UserGroupsService) Get(id string) (*UserGroup, error) { return nil, ErrUserGroupNotFound } +// Create creates a new user group +// userGroup: The user group configuration to create +// Returns the created user group and any error that occurred func (c *UserGroupsService) Create(userGroup *UserGroup) (*UserGroup, error) { userGroupJSON, err := json.Marshal(userGroup) if err != nil { @@ -128,6 +147,10 @@ func (c *UserGroupsService) Create(userGroup *UserGroup) (*UserGroup, error) { return &ug, nil } +// Update updates an existing user group +// id: The ID of the user group to update +// userGroup: The updated user group configuration +// Returns the updated user group and any error that occurred func (c *UserGroupsService) Update(id string, userGroup *UserGroup) (*UserGroup, error) { userGroupJSON, err := json.Marshal(userGroup) if err != nil { @@ -151,6 +174,9 @@ func (c *UserGroupsService) Update(id string, userGroup *UserGroup) (*UserGroup, return &ug, nil } +// Delete removes a user group by its ID +// id: The ID of the user group to delete +// Returns any error that occurred during deletion func (c *UserGroupsService) Delete(id string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/user-groups/%s", c.client.GetV1Url(), id), nil) if err != nil { diff --git a/cloudconnexa/users.go b/cloudconnexa/users.go index 7c14cac..134fa7b 100644 --- a/cloudconnexa/users.go +++ b/cloudconnexa/users.go @@ -9,9 +9,11 @@ import ( ) var ( + // ErrUserNotFound is returned when a user cannot be found ErrUserNotFound = errors.New("user not found") ) +// User represents a user configuration type User struct { ID string `json:"id"` Name string `json:"name"` @@ -27,6 +29,7 @@ type User struct { ConnectionStatus string `json:"connectionStatus"` } +// UserPageResponse represents a paginated response of users type UserPageResponse struct { Content []User `json:"content"` NumberOfElements int `json:"numberOfElements"` @@ -37,6 +40,7 @@ type UserPageResponse struct { TotalPages int `json:"totalPages"` } +// Device represents a user device configuration type Device struct { ID string `json:"id"` Name string `json:"name"` @@ -45,8 +49,13 @@ type Device struct { IPv6Address string `json:"ipV6Address"` } +// UsersService provides methods for managing users type UsersService service +// GetByPage retrieves users using pagination +// page: The page number to retrieve +// pageSize: The number of items per page +// Returns a page of users and any error that occurred func (c *UsersService) GetByPage(page int, pageSize int) (UserPageResponse, error) { endpoint := fmt.Sprintf("%s/users?page=%d&size=%d", c.client.GetV1Url(), page, pageSize) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -67,6 +76,10 @@ func (c *UsersService) GetByPage(page int, pageSize int) (UserPageResponse, erro return response, nil } +// List retrieves a user by username and role +// username: The username to search for +// role: The role to filter by +// Returns the user and any error that occurred func (c *UsersService) List(username string, role string) (*User, error) { pageSize := 10 page := 0 @@ -91,10 +104,16 @@ func (c *UsersService) List(username string, role string) (*User, error) { return nil, ErrUserNotFound } +// Get retrieves a user by ID +// userID: The ID of the user to retrieve +// Returns the user and any error that occurred func (c *UsersService) Get(userID string) (*User, error) { return c.GetByID(userID) } +// GetByID retrieves a user by ID +// userID: The ID of the user to retrieve +// Returns the user and any error that occurred func (c *UsersService) GetByID(userID string) (*User, error) { endpoint := fmt.Sprintf("%s/users/%s", c.client.GetV1Url(), userID) req, err := http.NewRequest(http.MethodGet, endpoint, nil) @@ -115,6 +134,9 @@ func (c *UsersService) GetByID(userID string) (*User, error) { return &user, nil } +// GetByUsername retrieves a user by username +// username: The username to search for +// Returns the user and any error that occurred func (c *UsersService) GetByUsername(username string) (*User, error) { pageSize := 10 page := 0 @@ -139,6 +161,9 @@ func (c *UsersService) GetByUsername(username string) (*User, error) { return nil, ErrUserNotFound } +// Create creates a new user +// user: The user configuration to create +// Returns the created user and any error that occurred func (c *UsersService) Create(user User) (*User, error) { userJSON, err := json.Marshal(user) if err != nil { @@ -163,6 +188,9 @@ func (c *UsersService) Create(user User) (*User, error) { return &u, nil } +// Update updates an existing user +// user: The user configuration to update +// Returns any error that occurred func (c *UsersService) Update(user User) error { userJSON, err := json.Marshal(user) if err != nil { @@ -181,6 +209,9 @@ func (c *UsersService) Update(user User) error { return nil } +// Delete deletes a user by ID +// userID: The ID of the user to delete +// Returns any error that occurred func (c *UsersService) Delete(userID string) error { req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/users/%s", c.client.GetV1Url(), userID), nil) if err != nil { diff --git a/cloudconnexa/vpn_regions.go b/cloudconnexa/vpn_regions.go index 4fe0daa..424236d 100644 --- a/cloudconnexa/vpn_regions.go +++ b/cloudconnexa/vpn_regions.go @@ -6,6 +6,7 @@ import ( "net/http" ) +// VpnRegion represents a VPN region configuration type VpnRegion struct { ID string `json:"id"` Continent string `json:"continent"` @@ -14,9 +15,11 @@ type VpnRegion struct { RegionName string `json:"regionName"` } +// VPNRegionsService provides methods for managing VPN regions type VPNRegionsService service // List retrieves all VPN regions +// Returns a slice of VPN regions and any error that occurred func (c *VPNRegionsService) List() ([]VpnRegion, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/regions", c.client.GetV1Url()), nil) if err != nil { @@ -37,6 +40,8 @@ func (c *VPNRegionsService) List() ([]VpnRegion, error) { } // GetByID retrieves a specific VPN region by ID +// regionID: The ID of the VPN region to retrieve +// Returns the VPN region and any error that occurred func (c *VPNRegionsService) GetByID(regionID string) (*VpnRegion, error) { req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/regions", c.client.GetV1Url()), nil) if err != nil { diff --git a/cloudconnexa/vpn_regions_test.go b/cloudconnexa/vpn_regions_test.go index cc9366d..f0e244f 100644 --- a/cloudconnexa/vpn_regions_test.go +++ b/cloudconnexa/vpn_regions_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" ) +// testVpnRegion represents a test VPN region configuration used in tests var testVpnRegion = VpnRegion{ ID: "test-region", Country: "Test Country", @@ -17,6 +18,8 @@ var testVpnRegion = VpnRegion{ RegionName: "Test Region", } +// TestVPNRegionsService_List tests the List method of VPNRegionsService +// It verifies that the service correctly retrieves and returns a list of VPN regions func TestVPNRegionsService_List(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Handle auth token request @@ -48,6 +51,8 @@ func TestVPNRegionsService_List(t *testing.T) { assert.Equal(t, testVpnRegion.ID, regions[0].ID) } +// TestVPNRegionsService_GetByID tests the GetByID method of VPNRegionsService +// It verifies that the service correctly retrieves a VPN region by ID and handles non-existent regions func TestVPNRegionsService_GetByID(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Handle auth token request diff --git a/e2e/client_test.go b/e2e/client_test.go index b0a04fe..eca5076 100644 --- a/e2e/client_test.go +++ b/e2e/client_test.go @@ -11,28 +11,36 @@ import ( "github.com/stretchr/testify/require" ) +// validateEnvVars checks if all required environment variables are set func validateEnvVars(t *testing.T) { validateEnvVar(t, HostEnvVar) validateEnvVar(t, ClientIDEnvVar) validateEnvVar(t, ClientSecretEnvVar) } +// validateEnvVar checks if a specific environment variable is set +// envVar: The name of the environment variable to check func validateEnvVar(t *testing.T, envVar string) { fmt.Println(os.Getenv(envVar)) require.NotEmptyf(t, os.Getenv(envVar), "%s must be set", envVar) } +// Environment variable names for client configuration const ( HostEnvVar = "OVPN_HOST" ClientIDEnvVar = "CLOUDCONNEXA_CLIENT_ID" - ClientSecretEnvVar = "CLOUDCONNEXA_CLIENT_SECRET" + ClientSecretEnvVar = "CLOUDCONNEXA_CLIENT_SECRET" //nolint:gosec // This is an environment variable name, not a credential ) +// TestNewClient tests the creation of a new client +// It verifies that the client is created successfully and has a valid token func TestNewClient(t *testing.T) { c := setUpClient(t) assert.NotEmpty(t, c.Token) } +// setUpClient creates and returns a new client for testing +// It validates environment variables and initializes the client with credentials func setUpClient(t *testing.T) *cloudconnexa.Client { validateEnvVars(t) var err error @@ -41,6 +49,8 @@ func setUpClient(t *testing.T) *cloudconnexa.Client { return client } +// TestListNetworks tests the retrieval of networks using pagination +// It verifies that networks can be retrieved successfully func TestListNetworks(t *testing.T) { c := setUpClient(t) response, err := c.Networks.GetByPage(0, 10) @@ -48,6 +58,8 @@ func TestListNetworks(t *testing.T) { fmt.Printf("found %d networks\n", len(response.Content)) } +// TestListConnectors tests the retrieval of network connectors using pagination +// It verifies that connectors can be retrieved successfully func TestListConnectors(t *testing.T) { c := setUpClient(t) response, err := c.NetworkConnectors.GetByPage(0, 10) @@ -55,6 +67,8 @@ func TestListConnectors(t *testing.T) { fmt.Printf("found %d connectors\n", len(response.Content)) } +// TestVPNRegions tests the VPN regions functionality +// It verifies that regions can be listed and retrieved by ID func TestVPNRegions(t *testing.T) { c := setUpClient(t) @@ -83,6 +97,8 @@ func TestVPNRegions(t *testing.T) { require.Nil(t, nonExistentRegion) } +// TestCreateNetwork tests the creation of a network with associated resources +// It verifies that a network can be created with routes and services, and then deleted func TestCreateNetwork(t *testing.T) { c := setUpClient(t) timestamp := time.Now().Unix()