Skip to content

Commit

Permalink
Add log shippings token API (#82)
Browse files Browse the repository at this point in the history
* initial

* refactor some fields, create integration test

* remove enable from request, export base url

* create test

* delete tests

* delete integration tests

* get test and integration test

* get available number tests

* retrieve test, integration test + fixes

* update test, integration test + fixes

* lint

* readme

* readme
  • Loading branch information
mirii1994 authored Jul 11, 2021
1 parent c79d79b commit 3030a9e
Show file tree
Hide file tree
Showing 33 changed files with 1,386 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,28 @@ endpoint, err := underTest.CreateEndpoint(endpoints.Endpoint{
})
```

##### Log Shipping Tokens

Compatible with Logz.io's [Manage Log Shipping Tokens API](https://docs.logz.io/api/#tag/Manage-log-shipping-tokens).
To create a new log shipping token:

```go
client, _ := log_shipping_tokens.New(apiToken, apiServerAddress)
token, err := client.CreateLogShippingToken(log_shipping_tokens.CreateLogShippingToken{
Name: "client_integration_test",
})
```

|function|func name|
|---|---|
|create log shipping token| `func (c *LogShippingTokensClient) CreateLogShippingToken(token CreateLogShippingToken) (*LogShippingToken, error)` |
|delete log shipping token| `func (c *LogShippingTokensClient) DeleteLogShippingToken(tokenId int32) error` |
|get log shipping token| `func (c *LogShippingTokensClient) GetLogShippingToken(tokenId int32) (*LogShippingToken, error)` |
|get available number of tokens| `func (c *LogShippingTokensClient) GetLogShippingLimitsToken() (*LogShippingTokensLimits, error)` |
|retrieve tokens| `func (c *LogShippingTokensClient) RetrieveLogShippingTokens(retrieveRequest RetrieveLogShippingTokensRequest) (*RetrieveLogShippingTokensResponse, error)` |
|update log shipping token| `func (c *LogShippingTokensClient) UpdateLogShippingToken(tokenId int32, token UpdateLogShippingToken) (*LogShippingToken, error)` |


#### Contributing

1. Clone this repo locally
Expand All @@ -172,6 +194,8 @@ endpoint, err := underTest.CreateEndpoint(endpoints.Endpoint{


### Changelog
- v1.6.0
- Add [log shipping tokens API](https://docs.logz.io/api/#tag/Manage-log-shipping-tokens) compatibility.
- v1.5.3
- Fix for `sub account`: return token & account id on Create.
- v1.5.2
Expand Down
138 changes: 138 additions & 0 deletions log_shipping_tokens/client_log_shipping_tokens.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package log_shipping_tokens

import (
"fmt"
"github.com/logzio/logzio_terraform_client"
"github.com/logzio/logzio_terraform_client/client"
"strconv"
)

const (
logShippingTokensServiceEndpoint string = "%s/v1/log-shipping/tokens"
)

const (
operationGetLogShippingToken = "GetLogShippingToken"
operationUpdateLogShippingToken = "UpdateLogShippingToken"
operationDeleteLogShippingToken = "DeleteLogShippingToken"
operationGetLogShippingTokensLimits = "GetNumberOfAvailableTokens"
operationRetrieveLogShippingTokens = "RetrieveLogShippingTokens"

retrieveSortFieldCreatedAtValue = "createdAt"
retrieveSortFieldNameValue = "name"
)

type LogShippingTokensClient struct {
*client.Client
}

type CreateLogShippingToken struct {
Name string `json:"name"`
}

type LogShippingToken struct {
Name string `json:"name"`
Id int32 `json:"id"`
Token string `json:"token"`
UpdatedAt float64 `json:"updatedAt"`
UpdatedBy string `json:"updatedBy"`
CreatedAt float64 `json:"createdAt"`
CreatedBy string `json:"createdBy"`
Enabled bool `json:"enabled"`
}

type LogShippingTokensLimits struct {
MaxAllowedTokens int32 `json:"maxAllowedTokens"` // The number of log shipping tokens this account can have.
NumOfEnabledTokens int32 `json:"numOfEnabledTokens"` // The number of log shipping tokens currently enabled for this account.
}

type RetrieveLogShippingTokensRequest struct {
Filter ShippingTokensFilterRequest `json:"filter"`
Sort []ShippingTokensSortRequest `json:"sort"`
Pagination ShippingTokensPaginationRequest `json:"pagination,omitempty"`
}

type ShippingTokensFilterRequest struct {
Enabled string `json:"enabled"`
}

type ShippingTokensSortRequest struct {
Field string `json:"field"`
Descending string `json:"descending"`
}

type ShippingTokensPaginationRequest struct {
PageNumber int32 `json:"pageNumber,omitempty"`
PageSize int32 `json:"pageSize,omitempty"`
}

type RetrieveLogShippingTokensResponse struct {
Total int32 `json:"total"`
Results []LogShippingToken `json:"results"`
Pagination ShippingTokensPaginationRequest `json:"pagination"`
}

type UpdateLogShippingToken struct {
Name string `json:"name"`
Enabled string `json:"enabled"`
}

func New(apiToken, baseUrl string) (*LogShippingTokensClient, error) {
if len(apiToken) == 0 {
return nil, fmt.Errorf("API token not defined")
}
if len(baseUrl) == 0 {
return nil, fmt.Errorf("Base URL not defined")
}
c := &LogShippingTokensClient{
Client: client.New(apiToken, baseUrl),
}

return c, nil
}

func validateCreateLogShippingTokenRequest(token CreateLogShippingToken) error {
if len(token.Name) == 0 {
return fmt.Errorf("name must be set")
}

return nil
}

func validateUpdateLogShippingTokenRequest(token UpdateLogShippingToken) error {
if len(token.Name) == 0 {
return fmt.Errorf("name must be set")
}

if len(token.Enabled) == 0 {
return fmt.Errorf("enabled must be set")
}

if token.Enabled != strconv.FormatBool(true) && token.Enabled != strconv.FormatBool(false) {
return fmt.Errorf("enabled must be %s or %s", strconv.FormatBool(true), strconv.FormatBool(false))
}

return nil
}

func validateRetrieveLogShippingTokensRequest(retrieveRequest RetrieveLogShippingTokensRequest) error {
if retrieveRequest.Filter.Enabled != strconv.FormatBool(true) && retrieveRequest.Filter.Enabled != strconv.FormatBool(false) {
return fmt.Errorf("filter.enabled must be %s or %s", strconv.FormatBool(true), strconv.FormatBool(false))
}

validSortFieldValues := []string{retrieveSortFieldCreatedAtValue, retrieveSortFieldNameValue}

if len(retrieveRequest.Sort) > 0 {
for _, sort := range retrieveRequest.Sort {
if !logzio_client.Contains(validSortFieldValues, sort.Field) {
return fmt.Errorf("sort's Field must be one of %s", validSortFieldValues)
}

if sort.Descending != strconv.FormatBool(true) && sort.Descending != strconv.FormatBool(false) {
return fmt.Errorf("sort.descending must be %s or %s", strconv.FormatBool(true), strconv.FormatBool(false))
}
}
}

return nil
}
56 changes: 56 additions & 0 deletions log_shipping_tokens/client_log_shipping_tokens_create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package log_shipping_tokens

import (
"bytes"
"encoding/json"
"fmt"
"github.com/logzio/logzio_terraform_client"
"net/http"
)

const createLogShippingTokenServiceUrl = logShippingTokensServiceEndpoint
const createLogShippingTokenServiceMethod string = http.MethodPost

type FieldError struct {
Field string
Message string
}

func (e FieldError) Error() string {
return fmt.Sprintf("%v: %v", e.Field, e.Message)
}

// Create a log shipping token, return the created token if successful, an error otherwise
func (c *LogShippingTokensClient) CreateLogShippingToken(token CreateLogShippingToken) (*LogShippingToken, error) {
err := validateCreateLogShippingTokenRequest(token)
if err != nil {
return nil, err
}

createToken, err := json.Marshal(token)
if err != nil {
return nil, err
}

req, _ := c.buildCreateApiRequest(c.ApiToken, createToken)
jsonResponse, err := logzio_client.CreateHttpRequestBytesResponse(req)
if err != nil {
return nil, err
}

var retVal LogShippingToken
err = json.Unmarshal(jsonResponse, &retVal)
if err != nil {
return nil, err
}

return &retVal, nil
}

func (c *LogShippingTokensClient) buildCreateApiRequest(apiToken string, jsonBytes []byte) (*http.Request, error) {
baseUrl := c.BaseUrl
req, err := http.NewRequest(createLogShippingTokenServiceMethod, fmt.Sprintf(createLogShippingTokenServiceUrl, baseUrl), bytes.NewBuffer(jsonBytes))
logzio_client.AddHttpHeaders(apiToken, req)

return req, err
}
45 changes: 45 additions & 0 deletions log_shipping_tokens/client_log_shipping_tokens_delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package log_shipping_tokens

import (
"fmt"
logzio_client "github.com/logzio/logzio_terraform_client"
"github.com/logzio/logzio_terraform_client/client"
"io/ioutil"
"net/http"
)

const deleteLogShippingTokenServiceMethod string = http.MethodDelete
const deleteLogShippingTokenServiceUrl = logShippingTokensServiceEndpoint + "/%d"
const deleteLogShippingTokenMethodSuccess int = http.StatusOK
const deleteLogShippingTokenMethodNotFound int = http.StatusNotFound

func (c *LogShippingTokensClient) buildDeleteApiRequest(apiToken string, tokenId int32) (*http.Request, error) {
baseUrl := c.BaseUrl
req, err := http.NewRequest(deleteLogShippingTokenServiceMethod, fmt.Sprintf(deleteLogShippingTokenServiceUrl, baseUrl, tokenId), nil)
logzio_client.AddHttpHeaders(apiToken, req)

return req, err
}

// Delete a log shipping token, specified by it's unique id, returns an error if a problem is encountered
func (c *LogShippingTokensClient) DeleteLogShippingToken(tokenId int32) error {
req, _ := c.buildDeleteApiRequest(c.ApiToken, tokenId)

httpClient := client.GetHttpClient(req)
resp, err := httpClient.Do(req)
if err != nil {
return err
}

jsonBytes, _ := ioutil.ReadAll(resp.Body)

if !logzio_client.CheckValidStatus(resp, []int{deleteLogShippingTokenMethodSuccess}) {
if resp.StatusCode == deleteLogShippingTokenMethodNotFound {
return fmt.Errorf("API call %s failed with missing log shipping token %d, data: %s", operationDeleteLogShippingToken, tokenId, jsonBytes)
}

return fmt.Errorf("API call %s failed with status code %d, data: %s", operationDeleteLogShippingToken, resp.StatusCode, jsonBytes)
}

return nil
}
52 changes: 52 additions & 0 deletions log_shipping_tokens/client_log_shipping_tokens_get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package log_shipping_tokens

import (
"encoding/json"
"fmt"
logzio_client "github.com/logzio/logzio_terraform_client"
"github.com/logzio/logzio_terraform_client/client"
"io/ioutil"
"net/http"
)

const getLogShippingTokenServiceUrl = logShippingTokensServiceEndpoint + "/%d"
const getLogShippingTokenServiceMethod string = http.MethodGet
const getLogShippingTokenMethodSuccess int = http.StatusOK
const getLogShippingTokenMethodNotFound int = http.StatusNotFound

func (c *LogShippingTokensClient) buildGetApiRequest(apiToken string, tokenId int32) (*http.Request, error) {
baseUrl := c.BaseUrl
req, err := http.NewRequest(getLogShippingTokenServiceMethod, fmt.Sprintf(getLogShippingTokenServiceUrl, baseUrl, tokenId), nil)
logzio_client.AddHttpHeaders(apiToken, req)

return req, err
}

// Returns a log shipping token given it's unique identifier, an error otherwise
func (c *LogShippingTokensClient) GetLogShippingToken(tokenId int32) (*LogShippingToken, error) {
req, _ := c.buildGetApiRequest(c.ApiToken, tokenId)
httpClient := client.GetHttpClient(req)
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

jsonBytes, _ := ioutil.ReadAll(resp.Body)

if !logzio_client.CheckValidStatus(resp, []int{getLogShippingTokenMethodSuccess}) {
if resp.StatusCode == getLogShippingTokenMethodNotFound {
return nil, fmt.Errorf("API call %s failed with missing log shipping token %d, data: %s", operationGetLogShippingToken, tokenId, jsonBytes)
}

return nil, fmt.Errorf("API call %s failed with status code %d, data: %s", operationGetLogShippingToken, resp.StatusCode, jsonBytes)
}

var token LogShippingToken
err = json.Unmarshal(jsonBytes, &token)
if err != nil {
return nil, err
}

return &token, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package log_shipping_tokens

import (
"encoding/json"
"fmt"
logzio_client "github.com/logzio/logzio_terraform_client"
"github.com/logzio/logzio_terraform_client/client"
"io/ioutil"
"net/http"
)

const getAvailableLogShippingTokensNumberServiceUrl = logShippingTokensServiceEndpoint + "/limits"
const getAvailableLogShippingTokensNumberServiceMethod string = http.MethodGet
const getAvailableLogShippingTokensNumberMethodSuccess int = http.StatusOK

func (c *LogShippingTokensClient) buildGetAvailableNumberApiRequest(apiToken string) (*http.Request, error) {
baseUrl := c.BaseUrl
req, err := http.NewRequest(getAvailableLogShippingTokensNumberServiceMethod, fmt.Sprintf(getAvailableLogShippingTokensNumberServiceUrl, baseUrl), nil)
logzio_client.AddHttpHeaders(apiToken, req)

return req, err
}

// Returns the number of log shipping tokens currently in use and the number of available tokens that can be enabled,
// error otherwise.
// Disabled tokens don't count against the token limit.
func (c *LogShippingTokensClient) GetLogShippingLimitsToken() (*LogShippingTokensLimits, error) {
req, _ := c.buildGetAvailableNumberApiRequest(c.ApiToken)
httpClient := client.GetHttpClient(req)
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

jsonBytes, _ := ioutil.ReadAll(resp.Body)

if !logzio_client.CheckValidStatus(resp, []int{getAvailableLogShippingTokensNumberMethodSuccess}) {
return nil, fmt.Errorf("API call %s failed with status code %d, data: %s", operationGetLogShippingTokensLimits, resp.StatusCode, jsonBytes)
}

var limits LogShippingTokensLimits
err = json.Unmarshal(jsonBytes, &limits)
if err != nil {
return nil, err
}

return &limits, nil
}
Loading

0 comments on commit 3030a9e

Please sign in to comment.