provider/datadog 9869: Validate credentials when initialising client. (#10567)
* provider/datadog 9869: Validate credentials when initialising client. * provider/datadog Pull in new version of go-datadog-api. * provider/datadog Update testAccCheckDatadogMonitorConfigNoThresholds test config.
This commit is contained in:
parent
a33f36218e
commit
10d68d90dd
|
@ -13,11 +13,10 @@ type Config struct {
|
|||
}
|
||||
|
||||
// Client returns a new Datadog client.
|
||||
func (c *Config) Client() (*datadog.Client, error) {
|
||||
func (c *Config) Client() *datadog.Client {
|
||||
|
||||
client := datadog.NewClient(c.APIKey, c.APPKey)
|
||||
|
||||
log.Printf("[INFO] Datadog Client configured ")
|
||||
|
||||
return client, nil
|
||||
return client
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package datadog
|
|||
import (
|
||||
"log"
|
||||
|
||||
"errors"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
@ -39,5 +40,17 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
|||
}
|
||||
|
||||
log.Println("[INFO] Initializing Datadog client")
|
||||
return config.Client()
|
||||
client := config.Client()
|
||||
|
||||
ok, err := client.Validate()
|
||||
|
||||
if err != nil {
|
||||
return client, err
|
||||
}
|
||||
|
||||
if ok == false {
|
||||
return client, errors.New(`No valid credential sources found for Datadog Provider. Please see https://terraform.io/docs/providers/datadog/index.html for more information on providing credentials for the Datadog Provider`)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
|
|
@ -78,9 +78,9 @@ func TestAccDatadogMonitor_BasicNoTreshold(t *testing.T) {
|
|||
resource.TestCheckResourceAttr(
|
||||
"datadog_monitor.foo", "locked", "false"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"datadog_monitor.foo", "tags.foo", "bar"),
|
||||
"datadog_monitor.foo", "tags.0", "foo:bar"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"datadog_monitor.foo", "tags.bar", "baz"),
|
||||
"datadog_monitor.foo", "tags.1", "bar:baz"),
|
||||
),
|
||||
},
|
||||
},
|
||||
|
@ -305,10 +305,7 @@ resource "datadog_monitor" "foo" {
|
|||
include_tags = true
|
||||
require_full_window = true
|
||||
locked = false
|
||||
tags {
|
||||
"foo" = "bar"
|
||||
"bar" = "baz"
|
||||
}
|
||||
tags = ["foo:bar", "bar:baz"]
|
||||
}
|
||||
`
|
||||
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
TEST?=.
|
||||
TEST?=$$(go list ./... | grep -v '/go-datadog-api/vendor/')
|
||||
VETARGS?=-asmdecl -atomic -bool -buildtags -copylocks -methods -nilfunc -printf -rangeloops -shift -structtags -unsafeptr
|
||||
GOFMT_FILES?=$$(find . -name '*.go' | grep -v vendor)
|
||||
|
||||
default: test
|
||||
|
||||
# get dependencies
|
||||
updatedeps:
|
||||
go list ./... \
|
||||
| xargs go list -f '{{join .Deps "\n"}}' \
|
||||
| grep -v go-datadog-api\
|
||||
| grep -v '/internal/' \
|
||||
| sort -u \
|
||||
| xargs go get -f -u -v
|
||||
default: test fmt
|
||||
|
||||
# test runs the unit tests and vets the code
|
||||
test:
|
||||
|
@ -25,14 +17,17 @@ testacc:
|
|||
testrace:
|
||||
go test -race $(TEST) $(TESTARGS)
|
||||
|
||||
fmt:
|
||||
gofmt -w $(GOFMT_FILES)
|
||||
|
||||
# vet runs the Go source code static analysis tool `vet` to find
|
||||
# any common errors.
|
||||
vet:
|
||||
@go tool vet 2>/dev/null ; if [ $$? -eq 3 ]; then \
|
||||
go get golang.org/x/tools/cmd/vet; \
|
||||
fi
|
||||
@echo "go tool vet $(VETARGS) $(TEST) "
|
||||
@go tool vet $(VETARGS) $(TEST) ; if [ $$? -eq 1 ]; then \
|
||||
@echo "go tool vet $(VETARGS)"
|
||||
@go tool vet $(VETARGS) $$(ls -d */ | grep -v vendor) ; if [ $$? -eq 1 ]; then \
|
||||
echo ""; \
|
||||
echo "Vet found suspicious constructs. Please check the reported constructs"; \
|
||||
echo "and fix them if necessary before submitting the code for review."; \
|
||||
|
|
|
@ -53,15 +53,13 @@ Thanks in advance! And, as always, patches welcome!
|
|||
|
||||
## DEVELOPMENT
|
||||
|
||||
* Get dependencies with `make updatedeps`.
|
||||
* Run tests tests with `make test`.
|
||||
* Integration tests can be run with `make testacc`.
|
||||
* Integration tests can be run with `make testacc`. Run specific integration tests with `make testacc TESTARGS='-run=TestCreateAndDeleteMonitor'`
|
||||
|
||||
The acceptance tests require _DATADOG_API_KEY_ and _DATADOG_APP_KEY_ to be available
|
||||
in your environment variables.
|
||||
|
||||
*Warning: the integrations tests will create and remove real resources in your Datadog
|
||||
account*
|
||||
*Warning: the integrations tests will create and remove real resources in your Datadog account.*
|
||||
|
||||
## COPYRIGHT AND LICENSE
|
||||
|
||||
|
|
|
@ -32,10 +32,9 @@ type reqAlerts struct {
|
|||
|
||||
// CreateAlert adds a new alert to the system. This returns a pointer to an
|
||||
// Alert so you can pass that to UpdateAlert later if needed.
|
||||
func (self *Client) CreateAlert(alert *Alert) (*Alert, error) {
|
||||
func (client *Client) CreateAlert(alert *Alert) (*Alert, error) {
|
||||
var out Alert
|
||||
err := self.doJsonRequest("POST", "/v1/alert", alert, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("POST", "/v1/alert", alert, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
|
@ -43,43 +42,41 @@ func (self *Client) CreateAlert(alert *Alert) (*Alert, error) {
|
|||
|
||||
// UpdateAlert takes an alert that was previously retrieved through some method
|
||||
// and sends it back to the server.
|
||||
func (self *Client) UpdateAlert(alert *Alert) error {
|
||||
return self.doJsonRequest("PUT", fmt.Sprintf("/v1/alert/%d", alert.Id),
|
||||
func (client *Client) UpdateAlert(alert *Alert) error {
|
||||
return client.doJsonRequest("PUT", fmt.Sprintf("/v1/alert/%d", alert.Id),
|
||||
alert, nil)
|
||||
}
|
||||
|
||||
// GetAlert retrieves an alert by identifier.
|
||||
func (self *Client) GetAlert(id int) (*Alert, error) {
|
||||
func (client *Client) GetAlert(id int) (*Alert, error) {
|
||||
var out Alert
|
||||
err := self.doJsonRequest("GET", fmt.Sprintf("/v1/alert/%d", id), nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", fmt.Sprintf("/v1/alert/%d", id), nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
// DeleteAlert removes an alert from the system.
|
||||
func (self *Client) DeleteAlert(id int) error {
|
||||
return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/alert/%d", id),
|
||||
func (client *Client) DeleteAlert(id int) error {
|
||||
return client.doJsonRequest("DELETE", fmt.Sprintf("/v1/alert/%d", id),
|
||||
nil, nil)
|
||||
}
|
||||
|
||||
// GetAlerts returns a slice of all alerts.
|
||||
func (self *Client) GetAlerts() ([]Alert, error) {
|
||||
func (client *Client) GetAlerts() ([]Alert, error) {
|
||||
var out reqAlerts
|
||||
err := self.doJsonRequest("GET", "/v1/alert", nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/alert", nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Alerts, nil
|
||||
}
|
||||
|
||||
// MuteAlerts turns off alerting notifications.
|
||||
func (self *Client) MuteAlerts() error {
|
||||
return self.doJsonRequest("POST", "/v1/mute_alerts", nil, nil)
|
||||
func (client *Client) MuteAlerts() error {
|
||||
return client.doJsonRequest("POST", "/v1/mute_alerts", nil, nil)
|
||||
}
|
||||
|
||||
// UnmuteAlerts turns on alerting notifications.
|
||||
func (self *Client) UnmuteAlerts() error {
|
||||
return self.doJsonRequest("POST", "/v1/unmute_alerts", nil, nil)
|
||||
func (client *Client) UnmuteAlerts() error {
|
||||
return client.doJsonRequest("POST", "/v1/unmute_alerts", nil, nil)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Datadog API for Go
|
||||
*
|
||||
* Please see the included LICENSE file for licensing information.
|
||||
*
|
||||
* Copyright 2013 by authors and contributors.
|
||||
*/
|
||||
|
||||
package datadog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Client is the object that handles talking to the Datadog API. This maintains
|
||||
// state information for a particular application connection.
|
||||
type Client struct {
|
||||
apiKey, appKey string
|
||||
|
||||
//The Http Client that is used to make requests
|
||||
HttpClient *http.Client
|
||||
}
|
||||
|
||||
// valid is the struct to unmarshal validation endpoint responses into.
|
||||
type valid struct {
|
||||
Errors []string `json:"errors"`
|
||||
IsValid bool `json:"valid"`
|
||||
}
|
||||
|
||||
// NewClient returns a new datadog.Client which can be used to access the API
|
||||
// methods. The expected argument is the API key.
|
||||
func NewClient(apiKey, appKey string) *Client {
|
||||
return &Client{
|
||||
apiKey: apiKey,
|
||||
appKey: appKey,
|
||||
HttpClient: http.DefaultClient,
|
||||
}
|
||||
}
|
||||
|
||||
// Validate checks if the API and application keys are valid.
|
||||
func (client *Client) Validate() (bool, error) {
|
||||
var bodyreader io.Reader
|
||||
var out valid
|
||||
req, err := http.NewRequest("GET", client.uriForAPI("/v1/validate"), bodyreader)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if bodyreader != nil {
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
var resp *http.Response
|
||||
resp, err = client.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Only care about 200 OK or 403 which we'll unmarshal into struct valid. Everything else is of no interest to us.
|
||||
if resp.StatusCode != 200 && resp.StatusCode != 403 {
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, fmt.Errorf("API error %s: %s", resp.Status, body)
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return out.IsValid, nil
|
||||
}
|
|
@ -28,11 +28,10 @@ type reqComment struct {
|
|||
}
|
||||
|
||||
// CreateComment adds a new comment to the system.
|
||||
func (self *Client) CreateComment(handle, message string) (*Comment, error) {
|
||||
func (client *Client) CreateComment(handle, message string) (*Comment, error) {
|
||||
var out reqComment
|
||||
comment := Comment{Handle: handle, Message: message}
|
||||
err := self.doJsonRequest("POST", "/v1/comments", &comment, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("POST", "/v1/comments", &comment, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out.Comment, nil
|
||||
|
@ -40,26 +39,25 @@ func (self *Client) CreateComment(handle, message string) (*Comment, error) {
|
|||
|
||||
// CreateRelatedComment adds a new comment, but lets you specify the related
|
||||
// identifier for the comment.
|
||||
func (self *Client) CreateRelatedComment(handle, message string,
|
||||
func (client *Client) CreateRelatedComment(handle, message string,
|
||||
relid int) (*Comment, error) {
|
||||
var out reqComment
|
||||
comment := Comment{Handle: handle, Message: message, RelatedId: relid}
|
||||
err := self.doJsonRequest("POST", "/v1/comments", &comment, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("POST", "/v1/comments", &comment, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out.Comment, nil
|
||||
}
|
||||
|
||||
// EditComment changes the message and possibly handle of a particular comment.
|
||||
func (self *Client) EditComment(id int, handle, message string) error {
|
||||
func (client *Client) EditComment(id int, handle, message string) error {
|
||||
comment := Comment{Handle: handle, Message: message}
|
||||
return self.doJsonRequest("PUT", fmt.Sprintf("/v1/comments/%d", id),
|
||||
return client.doJsonRequest("PUT", fmt.Sprintf("/v1/comments/%d", id),
|
||||
&comment, nil)
|
||||
}
|
||||
|
||||
// DeleteComment does exactly what you expect.
|
||||
func (self *Client) DeleteComment(id int) error {
|
||||
return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/comments/%d", id),
|
||||
func (client *Client) DeleteComment(id int) error {
|
||||
return client.doJsonRequest("DELETE", fmt.Sprintf("/v1/comments/%d", id),
|
||||
nil, nil)
|
||||
}
|
||||
|
|
|
@ -129,36 +129,33 @@ type DashboardConditionalFormat struct {
|
|||
}
|
||||
|
||||
// GetDashboard returns a single dashboard created on this account.
|
||||
func (self *Client) GetDashboard(id int) (*Dashboard, error) {
|
||||
func (client *Client) GetDashboard(id int) (*Dashboard, error) {
|
||||
var out reqGetDashboard
|
||||
err := self.doJsonRequest("GET", fmt.Sprintf("/v1/dash/%d", id), nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", fmt.Sprintf("/v1/dash/%d", id), nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out.Dashboard, nil
|
||||
}
|
||||
|
||||
// GetDashboards returns a list of all dashboards created on this account.
|
||||
func (self *Client) GetDashboards() ([]DashboardLite, error) {
|
||||
func (client *Client) GetDashboards() ([]DashboardLite, error) {
|
||||
var out reqGetDashboards
|
||||
err := self.doJsonRequest("GET", "/v1/dash", nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/dash", nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Dashboards, nil
|
||||
}
|
||||
|
||||
// DeleteDashboard deletes a dashboard by the identifier.
|
||||
func (self *Client) DeleteDashboard(id int) error {
|
||||
return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/dash/%d", id), nil, nil)
|
||||
func (client *Client) DeleteDashboard(id int) error {
|
||||
return client.doJsonRequest("DELETE", fmt.Sprintf("/v1/dash/%d", id), nil, nil)
|
||||
}
|
||||
|
||||
// CreateDashboard creates a new dashboard when given a Dashboard struct. Note
|
||||
// that the Id, Resource, Url and similar elements are not used in creation.
|
||||
func (self *Client) CreateDashboard(dash *Dashboard) (*Dashboard, error) {
|
||||
func (client *Client) CreateDashboard(dash *Dashboard) (*Dashboard, error) {
|
||||
var out reqGetDashboard
|
||||
err := self.doJsonRequest("POST", "/v1/dash", dash, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("POST", "/v1/dash", dash, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out.Dashboard, nil
|
||||
|
@ -166,7 +163,7 @@ func (self *Client) CreateDashboard(dash *Dashboard) (*Dashboard, error) {
|
|||
|
||||
// UpdateDashboard in essence takes a Dashboard struct and persists it back to
|
||||
// the server. Use this if you've updated your local and need to push it back.
|
||||
func (self *Client) UpdateDashboard(dash *Dashboard) error {
|
||||
return self.doJsonRequest("PUT", fmt.Sprintf("/v1/dash/%d", dash.Id),
|
||||
func (client *Client) UpdateDashboard(dash *Dashboard) error {
|
||||
return client.doJsonRequest("PUT", fmt.Sprintf("/v1/dash/%d", dash.Id),
|
||||
dash, nil)
|
||||
}
|
||||
|
|
|
@ -40,10 +40,9 @@ type reqDowntimes struct {
|
|||
// CreateDowntime adds a new downtme to the system. This returns a pointer
|
||||
// to a Downtime so you can pass that to UpdateDowntime or CancelDowntime
|
||||
// later if needed.
|
||||
func (self *Client) CreateDowntime(downtime *Downtime) (*Downtime, error) {
|
||||
func (client *Client) CreateDowntime(downtime *Downtime) (*Downtime, error) {
|
||||
var out Downtime
|
||||
err := self.doJsonRequest("POST", "/v1/downtime", downtime, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("POST", "/v1/downtime", downtime, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
|
@ -51,32 +50,30 @@ func (self *Client) CreateDowntime(downtime *Downtime) (*Downtime, error) {
|
|||
|
||||
// UpdateDowntime takes a downtime that was previously retrieved through some method
|
||||
// and sends it back to the server.
|
||||
func (self *Client) UpdateDowntime(downtime *Downtime) error {
|
||||
return self.doJsonRequest("PUT", fmt.Sprintf("/v1/downtime/%d", downtime.Id),
|
||||
func (client *Client) UpdateDowntime(downtime *Downtime) error {
|
||||
return client.doJsonRequest("PUT", fmt.Sprintf("/v1/downtime/%d", downtime.Id),
|
||||
downtime, nil)
|
||||
}
|
||||
|
||||
// Getdowntime retrieves an downtime by identifier.
|
||||
func (self *Client) GetDowntime(id int) (*Downtime, error) {
|
||||
func (client *Client) GetDowntime(id int) (*Downtime, error) {
|
||||
var out Downtime
|
||||
err := self.doJsonRequest("GET", fmt.Sprintf("/v1/downtime/%d", id), nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", fmt.Sprintf("/v1/downtime/%d", id), nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
// DeleteDowntime removes an downtime from the system.
|
||||
func (self *Client) DeleteDowntime(id int) error {
|
||||
return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/downtime/%d", id),
|
||||
func (client *Client) DeleteDowntime(id int) error {
|
||||
return client.doJsonRequest("DELETE", fmt.Sprintf("/v1/downtime/%d", id),
|
||||
nil, nil)
|
||||
}
|
||||
|
||||
// GetDowntimes returns a slice of all downtimes.
|
||||
func (self *Client) GetDowntimes() ([]Downtime, error) {
|
||||
func (client *Client) GetDowntimes() ([]Downtime, error) {
|
||||
var out reqDowntimes
|
||||
err := self.doJsonRequest("GET", "/v1/downtime", nil, &out.Downtimes)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/downtime", nil, &out.Downtimes); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Downtimes, nil
|
||||
|
|
|
@ -43,27 +43,25 @@ type reqGetEvents struct {
|
|||
}
|
||||
|
||||
// PostEvent takes as input an event and then posts it to the server.
|
||||
func (self *Client) PostEvent(event *Event) (*Event, error) {
|
||||
func (client *Client) PostEvent(event *Event) (*Event, error) {
|
||||
var out reqGetEvent
|
||||
err := self.doJsonRequest("POST", "/v1/events", event, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("POST", "/v1/events", event, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out.Event, nil
|
||||
}
|
||||
|
||||
// GetEvent gets a single event given an identifier.
|
||||
func (self *Client) GetEvent(id int) (*Event, error) {
|
||||
func (client *Client) GetEvent(id int) (*Event, error) {
|
||||
var out reqGetEvent
|
||||
err := self.doJsonRequest("GET", fmt.Sprintf("/v1/events/%d", id), nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", fmt.Sprintf("/v1/events/%d", id), nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out.Event, nil
|
||||
}
|
||||
|
||||
// QueryEvents returns a slice of events from the query stream.
|
||||
func (self *Client) GetEvents(start, end int,
|
||||
func (client *Client) GetEvents(start, end int,
|
||||
priority, sources, tags string) ([]Event, error) {
|
||||
// Since this is a GET request, we need to build a query string.
|
||||
vals := url.Values{}
|
||||
|
@ -81,9 +79,8 @@ func (self *Client) GetEvents(start, end int,
|
|||
|
||||
// Now the request and response.
|
||||
var out reqGetEvents
|
||||
err := self.doJsonRequest("GET",
|
||||
fmt.Sprintf("/v1/events?%s", vals.Encode()), nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET",
|
||||
fmt.Sprintf("/v1/events?%s", vals.Encode()), nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Events, nil
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Datadog API for Go
|
||||
*
|
||||
* Please see the included LICENSE file for licensing information.
|
||||
*
|
||||
* Copyright 2013 by authors and contributors.
|
||||
*/
|
||||
|
||||
package datadog
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Client is the object that handles talking to the Datadog API. This maintains
|
||||
// state information for a particular application connection.
|
||||
type Client struct {
|
||||
apiKey, appKey string
|
||||
|
||||
//The Http Client that is used to make requests
|
||||
HttpClient *http.Client
|
||||
}
|
||||
|
||||
// NewClient returns a new datadog.Client which can be used to access the API
|
||||
// methods. The expected argument is the API key.
|
||||
func NewClient(apiKey, appKey string) *Client {
|
||||
return &Client{
|
||||
apiKey: apiKey,
|
||||
appKey: appKey,
|
||||
HttpClient: http.DefaultClient,
|
||||
}
|
||||
}
|
|
@ -80,10 +80,10 @@ type reqMonitors struct {
|
|||
|
||||
// CreateMonitor adds a new monitor to the system. This returns a pointer to a
|
||||
// monitor so you can pass that to UpdateMonitor later if needed
|
||||
func (self *Client) CreateMonitor(monitor *Monitor) (*Monitor, error) {
|
||||
func (client *Client) CreateMonitor(monitor *Monitor) (*Monitor, error) {
|
||||
var out Monitor
|
||||
err := self.doJsonRequest("POST", "/v1/monitor", monitor, &out)
|
||||
if err != nil {
|
||||
// TODO: is this more pretty of frowned upon?
|
||||
if err := client.doJsonRequest("POST", "/v1/monitor", monitor, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
|
@ -91,16 +91,15 @@ func (self *Client) CreateMonitor(monitor *Monitor) (*Monitor, error) {
|
|||
|
||||
// UpdateMonitor takes a monitor that was previously retrieved through some method
|
||||
// and sends it back to the server
|
||||
func (self *Client) UpdateMonitor(monitor *Monitor) error {
|
||||
return self.doJsonRequest("PUT", fmt.Sprintf("/v1/monitor/%d", monitor.Id),
|
||||
func (client *Client) UpdateMonitor(monitor *Monitor) error {
|
||||
return client.doJsonRequest("PUT", fmt.Sprintf("/v1/monitor/%d", monitor.Id),
|
||||
monitor, nil)
|
||||
}
|
||||
|
||||
// GetMonitor retrieves a monitor by identifier
|
||||
func (self *Client) GetMonitor(id int) (*Monitor, error) {
|
||||
func (client *Client) GetMonitor(id int) (*Monitor, error) {
|
||||
var out Monitor
|
||||
err := self.doJsonRequest("GET", fmt.Sprintf("/v1/monitor/%d", id), nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", fmt.Sprintf("/v1/monitor/%d", id), nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
|
@ -137,37 +136,36 @@ func (self *Client) GetMonitorsByTags(tags []string) ([]Monitor, error) {
|
|||
}
|
||||
|
||||
// DeleteMonitor removes a monitor from the system
|
||||
func (self *Client) DeleteMonitor(id int) error {
|
||||
return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/monitor/%d", id),
|
||||
func (client *Client) DeleteMonitor(id int) error {
|
||||
return client.doJsonRequest("DELETE", fmt.Sprintf("/v1/monitor/%d", id),
|
||||
nil, nil)
|
||||
}
|
||||
|
||||
// GetMonitors returns a slice of all monitors
|
||||
func (self *Client) GetMonitors() ([]Monitor, error) {
|
||||
func (client *Client) GetMonitors() ([]Monitor, error) {
|
||||
var out reqMonitors
|
||||
err := self.doJsonRequest("GET", "/v1/monitor", nil, &out.Monitors)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/monitor", nil, &out.Monitors); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Monitors, nil
|
||||
}
|
||||
|
||||
// MuteMonitors turns off monitoring notifications
|
||||
func (self *Client) MuteMonitors() error {
|
||||
return self.doJsonRequest("POST", "/v1/monitor/mute_all", nil, nil)
|
||||
func (client *Client) MuteMonitors() error {
|
||||
return client.doJsonRequest("POST", "/v1/monitor/mute_all", nil, nil)
|
||||
}
|
||||
|
||||
// UnmuteMonitors turns on monitoring notifications
|
||||
func (self *Client) UnmuteMonitors() error {
|
||||
return self.doJsonRequest("POST", "/v1/monitor/unmute_all", nil, nil)
|
||||
func (client *Client) UnmuteMonitors() error {
|
||||
return client.doJsonRequest("POST", "/v1/monitor/unmute_all", nil, nil)
|
||||
}
|
||||
|
||||
// MuteMonitor turns off monitoring notifications for a monitor
|
||||
func (self *Client) MuteMonitor(id int) error {
|
||||
return self.doJsonRequest("POST", fmt.Sprintf("/v1/monitor/%d/mute", id), nil, nil)
|
||||
func (client *Client) MuteMonitor(id int) error {
|
||||
return client.doJsonRequest("POST", fmt.Sprintf("/v1/monitor/%d/mute", id), nil, nil)
|
||||
}
|
||||
|
||||
// UnmuteMonitor turns on monitoring notifications for a monitor
|
||||
func (self *Client) UnmuteMonitor(id int) error {
|
||||
return self.doJsonRequest("POST", fmt.Sprintf("/v1/monitor/%d/unmute", id), nil, nil)
|
||||
func (client *Client) UnmuteMonitor(id int) error {
|
||||
return client.doJsonRequest("POST", fmt.Sprintf("/v1/monitor/%d/unmute", id), nil, nil)
|
||||
}
|
||||
|
|
|
@ -25,23 +25,23 @@ import (
|
|||
|
||||
// uriForAPI is to be called with something like "/v1/events" and it will give
|
||||
// the proper request URI to be posted to.
|
||||
func (self *Client) uriForAPI(api string) string {
|
||||
func (client *Client) uriForAPI(api string) string {
|
||||
url := os.Getenv("DATADOG_HOST")
|
||||
if url == "" {
|
||||
url = "https://app.datadoghq.com"
|
||||
}
|
||||
if strings.Index(api, "?") > -1 {
|
||||
return url + "/api" + api + "&api_key=" +
|
||||
self.apiKey + "&application_key=" + self.appKey
|
||||
client.apiKey + "&application_key=" + client.appKey
|
||||
} else {
|
||||
return url + "/api" + api + "?api_key=" +
|
||||
self.apiKey + "&application_key=" + self.appKey
|
||||
client.apiKey + "&application_key=" + client.appKey
|
||||
}
|
||||
}
|
||||
|
||||
// doJsonRequest is the simplest type of request: a method on a URI that returns
|
||||
// some JSON result which we unmarshal into the passed interface.
|
||||
func (self *Client) doJsonRequest(method, api string,
|
||||
func (client *Client) doJsonRequest(method, api string,
|
||||
reqbody, out interface{}) error {
|
||||
// Handle the body if they gave us one.
|
||||
var bodyreader io.Reader
|
||||
|
@ -53,7 +53,7 @@ func (self *Client) doJsonRequest(method, api string,
|
|||
bodyreader = bytes.NewReader(bjson)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, self.uriForAPI(api), bodyreader)
|
||||
req, err := http.NewRequest(method, client.uriForAPI(api), bodyreader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ func (self *Client) doJsonRequest(method, api string,
|
|||
// Perform the request and retry it if it's not a POST request
|
||||
var resp *http.Response
|
||||
if method == "POST" {
|
||||
resp, err = self.HttpClient.Do(req)
|
||||
resp, err = client.HttpClient.Do(req)
|
||||
} else {
|
||||
resp, err = self.doRequestWithRetries(req, 60*time.Second)
|
||||
resp, err = client.doRequestWithRetries(req, 60*time.Second)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -98,8 +98,7 @@ func (self *Client) doJsonRequest(method, api string,
|
|||
body = []byte{'{', '}'}
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &out)
|
||||
if err != nil {
|
||||
if err := json.Unmarshal(body, &out); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -107,7 +106,7 @@ func (self *Client) doJsonRequest(method, api string,
|
|||
|
||||
// doRequestWithRetries performs an HTTP request repeatedly for maxTime or until
|
||||
// no error and no HTTP response code higher than 299 is returned.
|
||||
func (self *Client) doRequestWithRetries(req *http.Request, maxTime time.Duration) (*http.Response, error) {
|
||||
func (client *Client) doRequestWithRetries(req *http.Request, maxTime time.Duration) (*http.Response, error) {
|
||||
var (
|
||||
err error
|
||||
resp *http.Response
|
||||
|
@ -116,7 +115,7 @@ func (self *Client) doRequestWithRetries(req *http.Request, maxTime time.Duratio
|
|||
bo.MaxElapsedTime = maxTime
|
||||
|
||||
err = backoff.Retry(func() error {
|
||||
resp, err = self.HttpClient.Do(req)
|
||||
resp, err = client.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -62,35 +62,33 @@ type reqGetScreenboards struct {
|
|||
}
|
||||
|
||||
// GetScreenboard returns a single screenboard created on this account.
|
||||
func (self *Client) GetScreenboard(id int) (*Screenboard, error) {
|
||||
func (client *Client) GetScreenboard(id int) (*Screenboard, error) {
|
||||
out := &Screenboard{}
|
||||
err := self.doJsonRequest("GET", fmt.Sprintf("/v1/screen/%d", id), nil, out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", fmt.Sprintf("/v1/screen/%d", id), nil, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetScreenboards returns a list of all screenboards created on this account.
|
||||
func (self *Client) GetScreenboards() ([]*ScreenboardLite, error) {
|
||||
func (client *Client) GetScreenboards() ([]*ScreenboardLite, error) {
|
||||
var out reqGetScreenboards
|
||||
err := self.doJsonRequest("GET", "/v1/screen", nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/screen", nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Screenboards, nil
|
||||
}
|
||||
|
||||
// DeleteScreenboard deletes a screenboard by the identifier.
|
||||
func (self *Client) DeleteScreenboard(id int) error {
|
||||
return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/screen/%d", id), nil, nil)
|
||||
func (client *Client) DeleteScreenboard(id int) error {
|
||||
return client.doJsonRequest("DELETE", fmt.Sprintf("/v1/screen/%d", id), nil, nil)
|
||||
}
|
||||
|
||||
// CreateScreenboard creates a new screenboard when given a Screenboard struct. Note
|
||||
// that the Id, Resource, Url and similar elements are not used in creation.
|
||||
func (self *Client) CreateScreenboard(board *Screenboard) (*Screenboard, error) {
|
||||
func (client *Client) CreateScreenboard(board *Screenboard) (*Screenboard, error) {
|
||||
out := &Screenboard{}
|
||||
if err := self.doJsonRequest("POST", "/v1/screen", board, out); err != nil {
|
||||
if err := client.doJsonRequest("POST", "/v1/screen", board, out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
|
@ -98,8 +96,8 @@ func (self *Client) CreateScreenboard(board *Screenboard) (*Screenboard, error)
|
|||
|
||||
// UpdateScreenboard in essence takes a Screenboard struct and persists it back to
|
||||
// the server. Use this if you've updated your local and need to push it back.
|
||||
func (self *Client) UpdateScreenboard(board *Screenboard) error {
|
||||
return self.doJsonRequest("PUT", fmt.Sprintf("/v1/screen/%d", board.Id), board, nil)
|
||||
func (client *Client) UpdateScreenboard(board *Screenboard) error {
|
||||
return client.doJsonRequest("PUT", fmt.Sprintf("/v1/screen/%d", board.Id), board, nil)
|
||||
}
|
||||
|
||||
type ScreenShareResponse struct {
|
||||
|
@ -108,11 +106,11 @@ type ScreenShareResponse struct {
|
|||
}
|
||||
|
||||
// ShareScreenboard shares an existing screenboard, it takes and updates ScreenShareResponse
|
||||
func (self *Client) ShareScreenboard(id int, response *ScreenShareResponse) error {
|
||||
return self.doJsonRequest("GET", fmt.Sprintf("/v1/screen/share/%d", id), nil, response)
|
||||
func (client *Client) ShareScreenboard(id int, response *ScreenShareResponse) error {
|
||||
return client.doJsonRequest("GET", fmt.Sprintf("/v1/screen/share/%d", id), nil, response)
|
||||
}
|
||||
|
||||
// RevokeScreenboard revokes a currently shared screenboard
|
||||
func (self *Client) RevokeScreenboard(id int) error {
|
||||
return self.doJsonRequest("DELETE", fmt.Sprintf("/v1/screen/share/%d", id), nil, nil)
|
||||
func (client *Client) RevokeScreenboard(id int) error {
|
||||
return client.doJsonRequest("DELETE", fmt.Sprintf("/v1/screen/share/%d", id), nil, nil)
|
||||
}
|
||||
|
|
|
@ -17,20 +17,18 @@ type reqSearch struct {
|
|||
}
|
||||
|
||||
// SearchHosts searches through the hosts facet, returning matching hostnames.
|
||||
func (self *Client) SearchHosts(search string) ([]string, error) {
|
||||
func (client *Client) SearchHosts(search string) ([]string, error) {
|
||||
var out reqSearch
|
||||
err := self.doJsonRequest("GET", "/v1/search?q=hosts:"+search, nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/search?q=hosts:"+search, nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Results.Hosts, nil
|
||||
}
|
||||
|
||||
// SearchMetrics searches through the metrics facet, returning matching ones.
|
||||
func (self *Client) SearchMetrics(search string) ([]string, error) {
|
||||
func (client *Client) SearchMetrics(search string) ([]string, error) {
|
||||
var out reqSearch
|
||||
err := self.doJsonRequest("GET", "/v1/search?q=metrics:"+search, nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/search?q=metrics:"+search, nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Results.Metrics, nil
|
||||
|
|
|
@ -59,9 +59,8 @@ func (client *Client) PostMetrics(series []Metric) error {
|
|||
// timeseries data for that time peried
|
||||
func (client *Client) QueryMetrics(from, to int64, query string) ([]Series, error) {
|
||||
var out reqMetrics
|
||||
err := client.doJsonRequest("GET", "/v1/query?from="+strconv.FormatInt(from, 10)+"&to="+strconv.FormatInt(to, 10)+"&query="+query,
|
||||
nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/query?from="+strconv.FormatInt(from, 10)+"&to="+strconv.FormatInt(to, 10)+"&query="+query,
|
||||
nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Series, nil
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
)
|
||||
|
||||
// Snapshot creates an image from a graph and returns the URL of the image.
|
||||
func (self *Client) Snapshot(query string, start, end time.Time, eventQuery string) (string, error) {
|
||||
func (client *Client) Snapshot(query string, start, end time.Time, eventQuery string) (string, error) {
|
||||
v := url.Values{}
|
||||
v.Add("start", fmt.Sprintf("%d", start.Unix()))
|
||||
v.Add("end", fmt.Sprintf("%d", end.Unix()))
|
||||
|
@ -25,8 +25,7 @@ func (self *Client) Snapshot(query string, start, end time.Time, eventQuery stri
|
|||
out := struct {
|
||||
SnapshotURL string `json:"snapshot_url"`
|
||||
}{}
|
||||
err := self.doJsonRequest("GET", "/v1/graph/snapshot?"+v.Encode(), nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", "/v1/graph/snapshot?"+v.Encode(), nil, &out); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return out.SnapshotURL, nil
|
||||
|
|
|
@ -22,28 +22,26 @@ type reqGetHostTags struct {
|
|||
}
|
||||
|
||||
// GetTags returns a map of tags.
|
||||
func (self *Client) GetTags(source string) (TagMap, error) {
|
||||
func (client *Client) GetTags(source string) (TagMap, error) {
|
||||
var out reqGetTags
|
||||
uri := "/v1/tags/hosts"
|
||||
if source != "" {
|
||||
uri += "?source=" + source
|
||||
}
|
||||
err := self.doJsonRequest("GET", uri, nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", uri, nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Tags, nil
|
||||
}
|
||||
|
||||
// GetHostTags returns a slice of tags for a given host and source.
|
||||
func (self *Client) GetHostTags(host, source string) ([]string, error) {
|
||||
func (client *Client) GetHostTags(host, source string) ([]string, error) {
|
||||
var out reqGetHostTags
|
||||
uri := "/v1/tags/hosts/" + host
|
||||
if source != "" {
|
||||
uri += "?source=" + source
|
||||
}
|
||||
err := self.doJsonRequest("GET", uri, nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", uri, nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Tags, nil
|
||||
|
@ -51,14 +49,13 @@ func (self *Client) GetHostTags(host, source string) ([]string, error) {
|
|||
|
||||
// GetHostTagsBySource is a different way of viewing the tags. It returns a map
|
||||
// of source:[tag,tag].
|
||||
func (self *Client) GetHostTagsBySource(host, source string) (TagMap, error) {
|
||||
func (client *Client) GetHostTagsBySource(host, source string) (TagMap, error) {
|
||||
var out reqGetTags
|
||||
uri := "/v1/tags/hosts/" + host + "?by_source=true"
|
||||
if source != "" {
|
||||
uri += "&source=" + source
|
||||
}
|
||||
err := self.doJsonRequest("GET", uri, nil, &out)
|
||||
if err != nil {
|
||||
if err := client.doJsonRequest("GET", uri, nil, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Tags, nil
|
||||
|
@ -67,30 +64,30 @@ func (self *Client) GetHostTagsBySource(host, source string) (TagMap, error) {
|
|||
// AddTagsToHost does exactly what it says on the tin. Given a list of tags,
|
||||
// add them to the host. The source is optionally specificed, and defaults to
|
||||
// "users" as per the API documentation.
|
||||
func (self *Client) AddTagsToHost(host, source string, tags []string) error {
|
||||
func (client *Client) AddTagsToHost(host, source string, tags []string) error {
|
||||
uri := "/v1/tags/hosts/" + host
|
||||
if source != "" {
|
||||
uri += "?source=" + source
|
||||
}
|
||||
return self.doJsonRequest("POST", uri, reqGetHostTags{Tags: tags}, nil)
|
||||
return client.doJsonRequest("POST", uri, reqGetHostTags{Tags: tags}, nil)
|
||||
}
|
||||
|
||||
// UpdateHostTags overwrites existing tags for a host, allowing you to specify
|
||||
// a new set of tags for the given source. This defaults to "users".
|
||||
func (self *Client) UpdateHostTags(host, source string, tags []string) error {
|
||||
func (client *Client) UpdateHostTags(host, source string, tags []string) error {
|
||||
uri := "/v1/tags/hosts/" + host
|
||||
if source != "" {
|
||||
uri += "?source=" + source
|
||||
}
|
||||
return self.doJsonRequest("PUT", uri, reqGetHostTags{Tags: tags}, nil)
|
||||
return client.doJsonRequest("PUT", uri, reqGetHostTags{Tags: tags}, nil)
|
||||
}
|
||||
|
||||
// RemoveHostTags removes all tags from a host for the given source. If none is
|
||||
// given, the API defaults to "users".
|
||||
func (self *Client) RemoveHostTags(host, source string) error {
|
||||
func (client *Client) RemoveHostTags(host, source string) error {
|
||||
uri := "/v1/tags/hosts/" + host
|
||||
if source != "" {
|
||||
uri += "?source=" + source
|
||||
}
|
||||
return self.doJsonRequest("DELETE", uri, nil, nil)
|
||||
return client.doJsonRequest("DELETE", uri, nil, nil)
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ type reqInviteUsers struct {
|
|||
}
|
||||
|
||||
// InviteUsers takes a slice of email addresses and sends invitations to them.
|
||||
func (self *Client) InviteUsers(emails []string) error {
|
||||
return self.doJsonRequest("POST", "/v1/invite_users",
|
||||
func (client *Client) InviteUsers(emails []string) error {
|
||||
return client.doJsonRequest("POST", "/v1/invite_users",
|
||||
reqInviteUsers{Emails: emails}, nil)
|
||||
}
|
||||
|
||||
|
@ -54,10 +54,10 @@ type usersData struct {
|
|||
}
|
||||
|
||||
// GetUsers returns all user, or an error if not found
|
||||
func (self *Client) GetUsers() (users []User, err error) {
|
||||
func (client *Client) GetUsers() (users []User, err error) {
|
||||
var udata usersData
|
||||
uri := "/v1/user"
|
||||
err = self.doJsonRequest("GET", uri, nil, &udata)
|
||||
err = client.doJsonRequest("GET", uri, nil, &udata)
|
||||
users = udata.Users
|
||||
return
|
||||
}
|
||||
|
@ -68,23 +68,23 @@ type userData struct {
|
|||
}
|
||||
|
||||
// GetUser returns the user that match a handle, or an error if not found
|
||||
func (self *Client) GetUser(handle string) (user User, err error) {
|
||||
func (client *Client) GetUser(handle string) (user User, err error) {
|
||||
var udata userData
|
||||
uri := "/v1/user/" + handle
|
||||
err = self.doJsonRequest("GET", uri, nil, &udata)
|
||||
err = client.doJsonRequest("GET", uri, nil, &udata)
|
||||
user = udata.User
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateUser updates a user with the content of `user`,
|
||||
// and returns an error if the update failed
|
||||
func (self *Client) UpdateUser(user User) error {
|
||||
func (client *Client) UpdateUser(user User) error {
|
||||
uri := "/v1/user/" + user.Handle
|
||||
return self.doJsonRequest("PUT", uri, user, nil)
|
||||
return client.doJsonRequest("PUT", uri, user, nil)
|
||||
}
|
||||
|
||||
// DeleteUser deletes a user and returns an error if deletion failed
|
||||
func (self *Client) DeleteUser(handle string) error {
|
||||
func (client *Client) DeleteUser(handle string) error {
|
||||
uri := "/v1/user/" + handle
|
||||
return self.doJsonRequest("DELETE", uri, nil, nil)
|
||||
return client.doJsonRequest("DELETE", uri, nil, nil)
|
||||
}
|
||||
|
|
|
@ -2316,10 +2316,10 @@
|
|||
"revision": "75ce5fbba34b1912a3641adbd58cf317d7315821"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "U817qc0NaamC2zeUcZknLpnkrOw=",
|
||||
"checksumSHA1": "yMIu8wtilcyADHouhDllFm+kovE=",
|
||||
"path": "github.com/zorkian/go-datadog-api",
|
||||
"revision": "73d5b59ca18ee5e94fb449e001ed3f724fa0634e",
|
||||
"revisionTime": "2016-11-30T17:19:56Z"
|
||||
"revision": "a0a72fc5e4cae721b5144ba785f07f4edcf2cd47",
|
||||
"revisionTime": "2016-12-07T17:41:01Z"
|
||||
},
|
||||
{
|
||||
"path": "golang.org/x/crypto/curve25519",
|
||||
|
|
Loading…
Reference in New Issue