reg/clair/clair.go
Jessica Tracy 32589e90be Passing context (#163)
* passing context in layer calls

* more contexting

* clair folder and context in handlers

* fixed token transport to reuse request context

* tests

* taking out context pass in server handlers
2018-12-29 12:09:10 -05:00

116 lines
2.4 KiB
Go

package clair
import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"google.golang.org/grpc"
)
// Clair defines the client for retrieving information from the clair API.
type Clair struct {
URL string
Client *http.Client
Logf LogfCallback
grpcConn *grpc.ClientConn
}
// LogfCallback is the callback for formatting logs.
type LogfCallback func(format string, args ...interface{})
// Quiet discards logs silently.
func Quiet(format string, args ...interface{}) {}
// Log passes log messages to the logging package.
func Log(format string, args ...interface{}) {
log.Printf(format, args...)
}
// Opt holds the options for a new clair client.
type Opt struct {
Debug bool
Insecure bool
Timeout time.Duration
}
// New creates a new Clair struct with the given URL and credentials.
func New(url string, opt Opt) (*Clair, error) {
transport := http.DefaultTransport
grpcOpt := []grpc.DialOption{}
if opt.Insecure {
transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
grpcOpt = append(grpcOpt, grpc.WithInsecure())
}
errorTransport := &ErrorTransport{
Transport: transport,
}
// set the logging
logf := Quiet
if opt.Debug {
logf = Log
}
conn, err := grpc.Dial(url, grpcOpt...)
if err != nil {
logf("grpc dial %s failed: %v", url, err)
}
registry := &Clair{
URL: url,
Client: &http.Client{
Timeout: opt.Timeout,
Transport: errorTransport,
},
Logf: logf,
grpcConn: conn,
}
return registry, nil
}
// Close closes the gRPC connection
func (c *Clair) Close() error {
return c.grpcConn.Close()
}
// url returns a clair URL with the passed arguments concatenated.
func (c *Clair) url(pathTemplate string, args ...interface{}) string {
pathSuffix := fmt.Sprintf(pathTemplate, args...)
url := fmt.Sprintf("%s%s", c.URL, pathSuffix)
return url
}
func (c *Clair) getJSON(ctx context.Context, url string, response interface{}) (http.Header, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
resp, err := c.Client.Do(req.WithContext(ctx))
if err != nil {
return nil, err
}
defer resp.Body.Close()
c.Logf("clair.clair resp.Status=%s", resp.Status)
if err := json.NewDecoder(resp.Body).Decode(response); err != nil {
c.Logf("clair.clair resp.Status=%s, body=%s", resp.Status, response)
return nil, err
}
return resp.Header, nil
}