Updating go-checkpoint lib to have a fixed timeout

This commit is contained in:
Matt McQuillan 2017-10-10 12:30:07 -04:00 committed by Martin Atkins
parent ece099f453
commit 02404238a4
3 changed files with 122 additions and 4 deletions

View File

@ -1,7 +1,7 @@
# Go Checkpoint Client
[Checkpoint](http://checkpoint.hashicorp.com) is an internal service at
Hashicorp that we use to check version information, broadcoast security
Hashicorp that we use to check version information, broadcast security
bulletins, etc.
We understand that software making remote calls over the internet
@ -10,7 +10,7 @@ disabled in all of our software that includes it. You can view the source
of this client to see that we're not sending any private information.
Each Hashicorp application has it's specific configuration option
to disable chekpoint calls, but the `CHECKPOINT_DISABLE` makes
to disable checkpoint calls, but the `CHECKPOINT_DISABLE` makes
the underlying checkpoint component itself disabled. For example
in the case of packer:
```

View File

@ -3,6 +3,8 @@
package checkpoint
import (
"bytes"
"context"
"crypto/rand"
"encoding/binary"
"encoding/json"
@ -16,14 +18,118 @@ import (
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"time"
"github.com/hashicorp/go-cleanhttp"
uuid "github.com/hashicorp/go-uuid"
)
var magicBytes [4]byte = [4]byte{0x35, 0x77, 0x69, 0xFB}
// ReportParams are the parameters for configuring a telemetry report.
type ReportParams struct {
// Signature is some random signature that should be stored and used
// as a cookie-like value. This ensures that alerts aren't repeated.
// If the signature is changed, repeat alerts may be sent down. The
// signature should NOT be anything identifiable to a user (such as
// a MAC address). It should be random.
//
// If SignatureFile is given, then the signature will be read from this
// file. If the file doesn't exist, then a random signature will
// automatically be generated and stored here. SignatureFile will be
// ignored if Signature is given.
Signature string `json:"signature"`
SignatureFile string `json:"-"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
Arch string `json:"arch"`
OS string `json:"os"`
Payload interface{} `json:"payload,omitempty"`
Product string `json:"product"`
RunID string `json:"run_id"`
SchemaVersion string `json:"schema_version"`
Version string `json:"version"`
}
func (i *ReportParams) signature() string {
signature := i.Signature
if i.Signature == "" && i.SignatureFile != "" {
var err error
signature, err = checkSignature(i.SignatureFile)
if err != nil {
return ""
}
}
return signature
}
// Report sends telemetry information to checkpoint
func Report(ctx context.Context, r *ReportParams) error {
if disabled := os.Getenv("CHECKPOINT_DISABLE"); disabled != "" {
return nil
}
req, err := ReportRequest(r)
if err != nil {
return err
}
client := cleanhttp.DefaultClient()
resp, err := client.Do(req.WithContext(ctx))
if err != nil {
return err
}
if resp.StatusCode != 201 {
return fmt.Errorf("Unknown status: %d", resp.StatusCode)
}
return nil
}
// ReportRequest creates a request object for making a report
func ReportRequest(r *ReportParams) (*http.Request, error) {
// Populate some fields automatically if we can
if r.RunID == "" {
uuid, err := uuid.GenerateUUID()
if err != nil {
return nil, err
}
r.RunID = uuid
}
if r.Arch == "" {
r.Arch = runtime.GOARCH
}
if r.OS == "" {
r.OS = runtime.GOOS
}
if r.Signature == "" {
r.Signature = r.signature()
}
b, err := json.Marshal(r)
if err != nil {
return nil, err
}
u := &url.URL{
Scheme: "https",
Host: "checkpoint-api.hashicorp.com",
Path: fmt.Sprintf("/v1/telemetry/%s", r.Product),
}
req, err := http.NewRequest("POST", u.String(), bytes.NewReader(b))
if err != nil {
return nil, err
}
req.Header.Add("Accept", "application/json")
req.Header.Add("User-Agent", "HashiCorp/go-checkpoint")
return req, nil
}
// CheckParams are the parameters for configuring a check request.
type CheckParams struct {
// Product and version are used to lookup the correct product and
@ -99,6 +205,12 @@ func Check(p *CheckParams) (*CheckResponse, error) {
return &CheckResponse{}, nil
}
// set a default timeout of 3 sec for the check request (in milliseconds)
timeout := 3000
if _, err := strconv.Atoi(os.Getenv("CHECKPOINT_TIMEOUT")); err == nil {
timeout, _ = strconv.Atoi(os.Getenv("CHECKPOINT_TIMEOUT"))
}
// If we have a cached result, then use that
if r, err := checkCache(p.Version, p.CacheFile, p.CacheDuration); err != nil {
return nil, err
@ -145,6 +257,11 @@ func Check(p *CheckParams) (*CheckResponse, error) {
req.Header.Add("User-Agent", "HashiCorp/go-checkpoint")
client := cleanhttp.DefaultClient()
// We use a short timeout since checking for new versions is not critical
// enough to block on if checkpoint is broken/slow.
client.Timeout = time.Duration(timeout) * time.Millisecond
resp, err := client.Do(req)
if err != nil {
return nil, err

5
vendor/vendor.json vendored
View File

@ -1421,9 +1421,10 @@
"revision": "7554cd9344cec97297fa6649b055a8c98c2a1e55"
},
{
"checksumSHA1": "nd3S1qkFv7zZxA9be0bw4nT0pe0=",
"checksumSHA1": "D267IUMW2rcb+vNe3QU+xhfSrgY=",
"path": "github.com/hashicorp/go-checkpoint",
"revision": "e4b2dc34c0f698ee04750bf2035d8b9384233e1b"
"revision": "1545e56e46dec3bba264e41fde2c1e2aa65b5dd4",
"revisionTime": "2017-10-09T17:35:28Z"
},
{
"checksumSHA1": "b8F628srIitj5p7Y130xc9k0QWs=",