api: v2 api with gRPC and gRPC-gateway
Newly designed API defines Ancestry as a set of layers and shrinked the api to only the most used apis: post ancestry, get layer, get notification, delete notification Fixes #98
This commit is contained in:
parent
abd7d2e013
commit
a4edf38566
@ -1,4 +1,8 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.8
|
||||
|
||||
sudo: required
|
||||
|
||||
install:
|
||||
|
13
api/api.go
13
api/api.go
@ -26,6 +26,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tylerb/graceful"
|
||||
|
||||
"github.com/coreos/clair/api/v2"
|
||||
"github.com/coreos/clair/database"
|
||||
"github.com/coreos/clair/pkg/stopper"
|
||||
)
|
||||
@ -35,12 +36,24 @@ const timeoutResponse = `{"Error":{"Message":"Clair failed to respond within the
|
||||
// Config is the configuration for the API service.
|
||||
type Config struct {
|
||||
Port int
|
||||
GrpcPort int
|
||||
HealthPort int
|
||||
Timeout time.Duration
|
||||
PaginationKey string
|
||||
CertFile, KeyFile, CAFile string
|
||||
}
|
||||
|
||||
func RunV2(cfg *Config, store database.Datastore) {
|
||||
tlsConfig, err := tlsClientConfig(cfg.CAFile)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("could not initialize client cert authentication")
|
||||
}
|
||||
if tlsConfig != nil {
|
||||
log.Info("main API configured with client certificate authentication")
|
||||
}
|
||||
v2.Run(cfg.GrpcPort, tlsConfig, cfg.PaginationKey, cfg.CertFile, cfg.KeyFile, store)
|
||||
}
|
||||
|
||||
func Run(cfg *Config, store database.Datastore, st *stopper.Stopper) {
|
||||
defer st.End()
|
||||
|
||||
|
49
api/token/token.go
Normal file
49
api/token/token.go
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2017 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package token implements encryption/decryption for json encoded interfaces
|
||||
package token
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/fernet/fernet-go"
|
||||
)
|
||||
|
||||
// Unmarshal decrypts a token using provided key
|
||||
// and decode the result into interface.
|
||||
func Unmarshal(token string, key string, v interface{}) error {
|
||||
k, _ := fernet.DecodeKey(key)
|
||||
msg := fernet.VerifyAndDecrypt([]byte(token), time.Hour, []*fernet.Key{k})
|
||||
if msg == nil {
|
||||
return errors.New("invalid or expired pagination token")
|
||||
}
|
||||
|
||||
return json.NewDecoder(bytes.NewBuffer(msg)).Decode(&v)
|
||||
}
|
||||
|
||||
// Marshal encodes an interface into json bytes and encrypts it.
|
||||
func Marshal(v interface{}, key string) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
err := json.NewEncoder(&buf).Encode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k, _ := fernet.DecodeKey(key)
|
||||
return fernet.EncryptAndSign(buf.Bytes(), k)
|
||||
}
|
@ -15,14 +15,9 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/fernet/fernet-go"
|
||||
|
||||
"github.com/coreos/clair/api/token"
|
||||
"github.com/coreos/clair/database"
|
||||
"github.com/coreos/clair/ext/versionfmt"
|
||||
)
|
||||
@ -227,7 +222,7 @@ func NotificationFromDatabaseModel(dbNotification database.VulnerabilityNotifica
|
||||
|
||||
var nextPageStr string
|
||||
if nextPage != database.NoVulnerabilityNotificationPage {
|
||||
nextPageBytes, _ := tokenMarshal(nextPage, key)
|
||||
nextPageBytes, _ := token.Marshal(nextPage, key)
|
||||
nextPageStr = string(nextPageBytes)
|
||||
}
|
||||
|
||||
@ -320,24 +315,3 @@ type FeatureEnvelope struct {
|
||||
Features *[]Feature `json:"Features,omitempty"`
|
||||
Error *Error `json:"Error,omitempty"`
|
||||
}
|
||||
|
||||
func tokenUnmarshal(token string, key string, v interface{}) error {
|
||||
k, _ := fernet.DecodeKey(key)
|
||||
msg := fernet.VerifyAndDecrypt([]byte(token), time.Hour, []*fernet.Key{k})
|
||||
if msg == nil {
|
||||
return errors.New("invalid or expired pagination token")
|
||||
}
|
||||
|
||||
return json.NewDecoder(bytes.NewBuffer(msg)).Decode(&v)
|
||||
}
|
||||
|
||||
func tokenMarshal(v interface{}, key string) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
err := json.NewEncoder(&buf).Encode(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k, _ := fernet.DecodeKey(key)
|
||||
return fernet.EncryptAndSign(buf.Bytes(), k)
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/coreos/clair"
|
||||
"github.com/coreos/clair/api/token"
|
||||
"github.com/coreos/clair/database"
|
||||
"github.com/coreos/clair/pkg/commonerr"
|
||||
"github.com/coreos/clair/pkg/tarutil"
|
||||
@ -209,7 +210,7 @@ func getVulnerabilities(w http.ResponseWriter, r *http.Request, p httprouter.Par
|
||||
page := 0
|
||||
pageStrs, pageExists := query["page"]
|
||||
if pageExists {
|
||||
err = tokenUnmarshal(pageStrs[0], ctx.PaginationKey, &page)
|
||||
err = token.Unmarshal(pageStrs[0], ctx.PaginationKey, &page)
|
||||
if err != nil {
|
||||
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"invalid page format: " + err.Error()}})
|
||||
return getNotificationRoute, http.StatusBadRequest
|
||||
@ -239,7 +240,7 @@ func getVulnerabilities(w http.ResponseWriter, r *http.Request, p httprouter.Par
|
||||
|
||||
var nextPageStr string
|
||||
if nextPage != -1 {
|
||||
nextPageBytes, err := tokenMarshal(nextPage, ctx.PaginationKey)
|
||||
nextPageBytes, err := token.Marshal(nextPage, ctx.PaginationKey)
|
||||
if err != nil {
|
||||
writeResponse(w, r, http.StatusBadRequest, VulnerabilityEnvelope{Error: &Error{"failed to marshal token: " + err.Error()}})
|
||||
return getNotificationRoute, http.StatusBadRequest
|
||||
@ -452,14 +453,14 @@ func getNotification(w http.ResponseWriter, r *http.Request, p httprouter.Params
|
||||
page := database.VulnerabilityNotificationFirstPage
|
||||
pageStrs, pageExists := query["page"]
|
||||
if pageExists {
|
||||
err := tokenUnmarshal(pageStrs[0], ctx.PaginationKey, &page)
|
||||
err := token.Unmarshal(pageStrs[0], ctx.PaginationKey, &page)
|
||||
if err != nil {
|
||||
writeResponse(w, r, http.StatusBadRequest, NotificationEnvelope{Error: &Error{"invalid page format: " + err.Error()}})
|
||||
return getNotificationRoute, http.StatusBadRequest
|
||||
}
|
||||
pageToken = pageStrs[0]
|
||||
} else {
|
||||
pageTokenBytes, err := tokenMarshal(page, ctx.PaginationKey)
|
||||
pageTokenBytes, err := token.Marshal(page, ctx.PaginationKey)
|
||||
if err != nil {
|
||||
writeResponse(w, r, http.StatusBadRequest, NotificationEnvelope{Error: &Error{"failed to marshal token: " + err.Error()}})
|
||||
return getNotificationRoute, http.StatusBadRequest
|
||||
|
17
api/v2/clairpb/Makefile
Normal file
17
api/v2/clairpb/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
all:
|
||||
protoc -I/usr/local/include -I. \
|
||||
-I${GOPATH}/src \
|
||||
-I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
||||
--go_out=plugins=grpc:. \
|
||||
clair.proto
|
||||
protoc -I/usr/local/include -I. \
|
||||
-I${GOPATH}/src \
|
||||
-I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
||||
--grpc-gateway_out=logtostderr=true:. \
|
||||
clair.proto
|
||||
protoc -I/usr/local/include -I. \
|
||||
-I${GOPATH}/src \
|
||||
-I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
||||
--swagger_out=logtostderr=true:. \
|
||||
clair.proto
|
||||
go generate .
|
872
api/v2/clairpb/clair.pb.go
Normal file
872
api/v2/clairpb/clair.pb.go
Normal file
@ -0,0 +1,872 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: clair.proto
|
||||
|
||||
/*
|
||||
Package clairpb is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
clair.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Vulnerability
|
||||
Feature
|
||||
Ancestry
|
||||
LayersIntroducingVulnerabilty
|
||||
OrderedLayerName
|
||||
Layer
|
||||
Notification
|
||||
Page
|
||||
PostAncestryRequest
|
||||
PostAncestryResponse
|
||||
GetAncestryRequest
|
||||
GetAncestryResponse
|
||||
GetNotificationRequest
|
||||
GetNotificationResponse
|
||||
DeleteNotificationRequest
|
||||
*/
|
||||
package clairpb
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
import google_protobuf1 "github.com/golang/protobuf/ptypes/empty"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Vulnerability struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
NamespaceName string `protobuf:"bytes,2,opt,name=namespace_name,json=namespaceName" json:"namespace_name,omitempty"`
|
||||
Description string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"`
|
||||
Link string `protobuf:"bytes,4,opt,name=link" json:"link,omitempty"`
|
||||
Severity string `protobuf:"bytes,5,opt,name=severity" json:"severity,omitempty"`
|
||||
Metadata string `protobuf:"bytes,6,opt,name=metadata" json:"metadata,omitempty"`
|
||||
FixedBy string `protobuf:"bytes,7,opt,name=fixed_by,json=fixedBy" json:"fixed_by,omitempty"`
|
||||
FixedInFeatures []*Feature `protobuf:"bytes,8,rep,name=fixed_in_features,json=fixedInFeatures" json:"fixed_in_features,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Vulnerability) Reset() { *m = Vulnerability{} }
|
||||
func (m *Vulnerability) String() string { return proto.CompactTextString(m) }
|
||||
func (*Vulnerability) ProtoMessage() {}
|
||||
func (*Vulnerability) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func (m *Vulnerability) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Vulnerability) GetNamespaceName() string {
|
||||
if m != nil {
|
||||
return m.NamespaceName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Vulnerability) GetDescription() string {
|
||||
if m != nil {
|
||||
return m.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Vulnerability) GetLink() string {
|
||||
if m != nil {
|
||||
return m.Link
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Vulnerability) GetSeverity() string {
|
||||
if m != nil {
|
||||
return m.Severity
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Vulnerability) GetMetadata() string {
|
||||
if m != nil {
|
||||
return m.Metadata
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Vulnerability) GetFixedBy() string {
|
||||
if m != nil {
|
||||
return m.FixedBy
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Vulnerability) GetFixedInFeatures() []*Feature {
|
||||
if m != nil {
|
||||
return m.FixedInFeatures
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Feature struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
NamespaceName string `protobuf:"bytes,2,opt,name=namespace_name,json=namespaceName" json:"namespace_name,omitempty"`
|
||||
Version string `protobuf:"bytes,3,opt,name=version" json:"version,omitempty"`
|
||||
VersionFormat string `protobuf:"bytes,4,opt,name=version_format,json=versionFormat" json:"version_format,omitempty"`
|
||||
AddedBy string `protobuf:"bytes,5,opt,name=added_by,json=addedBy" json:"added_by,omitempty"`
|
||||
Vulnerabilities []*Vulnerability `protobuf:"bytes,6,rep,name=vulnerabilities" json:"vulnerabilities,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Feature) Reset() { *m = Feature{} }
|
||||
func (m *Feature) String() string { return proto.CompactTextString(m) }
|
||||
func (*Feature) ProtoMessage() {}
|
||||
func (*Feature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Feature) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Feature) GetNamespaceName() string {
|
||||
if m != nil {
|
||||
return m.NamespaceName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Feature) GetVersion() string {
|
||||
if m != nil {
|
||||
return m.Version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Feature) GetVersionFormat() string {
|
||||
if m != nil {
|
||||
return m.VersionFormat
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Feature) GetAddedBy() string {
|
||||
if m != nil {
|
||||
return m.AddedBy
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Feature) GetVulnerabilities() []*Vulnerability {
|
||||
if m != nil {
|
||||
return m.Vulnerabilities
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Ancestry struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
EngineVersion int32 `protobuf:"varint,2,opt,name=engine_version,json=engineVersion" json:"engine_version,omitempty"`
|
||||
Layers []*Layer `protobuf:"bytes,3,rep,name=layers" json:"layers,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Ancestry) Reset() { *m = Ancestry{} }
|
||||
func (m *Ancestry) String() string { return proto.CompactTextString(m) }
|
||||
func (*Ancestry) ProtoMessage() {}
|
||||
func (*Ancestry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
|
||||
func (m *Ancestry) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Ancestry) GetEngineVersion() int32 {
|
||||
if m != nil {
|
||||
return m.EngineVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Ancestry) GetLayers() []*Layer {
|
||||
if m != nil {
|
||||
return m.Layers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type LayersIntroducingVulnerabilty struct {
|
||||
Vulnerability *Vulnerability `protobuf:"bytes,1,opt,name=vulnerability" json:"vulnerability,omitempty"`
|
||||
Layers []*OrderedLayerName `protobuf:"bytes,2,rep,name=layers" json:"layers,omitempty"`
|
||||
}
|
||||
|
||||
func (m *LayersIntroducingVulnerabilty) Reset() { *m = LayersIntroducingVulnerabilty{} }
|
||||
func (m *LayersIntroducingVulnerabilty) String() string { return proto.CompactTextString(m) }
|
||||
func (*LayersIntroducingVulnerabilty) ProtoMessage() {}
|
||||
func (*LayersIntroducingVulnerabilty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *LayersIntroducingVulnerabilty) GetVulnerability() *Vulnerability {
|
||||
if m != nil {
|
||||
return m.Vulnerability
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *LayersIntroducingVulnerabilty) GetLayers() []*OrderedLayerName {
|
||||
if m != nil {
|
||||
return m.Layers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type OrderedLayerName struct {
|
||||
Index int32 `protobuf:"varint,1,opt,name=index" json:"index,omitempty"`
|
||||
LayerName string `protobuf:"bytes,2,opt,name=layer_name,json=layerName" json:"layer_name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *OrderedLayerName) Reset() { *m = OrderedLayerName{} }
|
||||
func (m *OrderedLayerName) String() string { return proto.CompactTextString(m) }
|
||||
func (*OrderedLayerName) ProtoMessage() {}
|
||||
func (*OrderedLayerName) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
|
||||
func (m *OrderedLayerName) GetIndex() int32 {
|
||||
if m != nil {
|
||||
return m.Index
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *OrderedLayerName) GetLayerName() string {
|
||||
if m != nil {
|
||||
return m.LayerName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Layer struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
NamespaceNames []string `protobuf:"bytes,2,rep,name=namespace_names,json=namespaceNames" json:"namespace_names,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Layer) Reset() { *m = Layer{} }
|
||||
func (m *Layer) String() string { return proto.CompactTextString(m) }
|
||||
func (*Layer) ProtoMessage() {}
|
||||
func (*Layer) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||
|
||||
func (m *Layer) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Layer) GetNamespaceNames() []string {
|
||||
if m != nil {
|
||||
return m.NamespaceNames
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Created string `protobuf:"bytes,2,opt,name=created" json:"created,omitempty"`
|
||||
Notified string `protobuf:"bytes,3,opt,name=notified" json:"notified,omitempty"`
|
||||
Deleted string `protobuf:"bytes,4,opt,name=deleted" json:"deleted,omitempty"`
|
||||
Limit int32 `protobuf:"varint,5,opt,name=limit" json:"limit,omitempty"`
|
||||
Page *Page `protobuf:"bytes,6,opt,name=page" json:"page,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Notification) Reset() { *m = Notification{} }
|
||||
func (m *Notification) String() string { return proto.CompactTextString(m) }
|
||||
func (*Notification) ProtoMessage() {}
|
||||
func (*Notification) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
||||
|
||||
func (m *Notification) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Notification) GetCreated() string {
|
||||
if m != nil {
|
||||
return m.Created
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Notification) GetNotified() string {
|
||||
if m != nil {
|
||||
return m.Notified
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Notification) GetDeleted() string {
|
||||
if m != nil {
|
||||
return m.Deleted
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Notification) GetLimit() int32 {
|
||||
if m != nil {
|
||||
return m.Limit
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Notification) GetPage() *Page {
|
||||
if m != nil {
|
||||
return m.Page
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Page struct {
|
||||
ThisToken string `protobuf:"bytes,1,opt,name=this_token,json=thisToken" json:"this_token,omitempty"`
|
||||
NextToken string `protobuf:"bytes,2,opt,name=next_token,json=nextToken" json:"next_token,omitempty"`
|
||||
Old *LayersIntroducingVulnerabilty `protobuf:"bytes,3,opt,name=old" json:"old,omitempty"`
|
||||
New *LayersIntroducingVulnerabilty `protobuf:"bytes,4,opt,name=new" json:"new,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Page) Reset() { *m = Page{} }
|
||||
func (m *Page) String() string { return proto.CompactTextString(m) }
|
||||
func (*Page) ProtoMessage() {}
|
||||
func (*Page) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||
|
||||
func (m *Page) GetThisToken() string {
|
||||
if m != nil {
|
||||
return m.ThisToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Page) GetNextToken() string {
|
||||
if m != nil {
|
||||
return m.NextToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Page) GetOld() *LayersIntroducingVulnerabilty {
|
||||
if m != nil {
|
||||
return m.Old
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Page) GetNew() *LayersIntroducingVulnerabilty {
|
||||
if m != nil {
|
||||
return m.New
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PostAncestryRequest struct {
|
||||
AncestryName string `protobuf:"bytes,1,opt,name=ancestry_name,json=ancestryName" json:"ancestry_name,omitempty"`
|
||||
Format string `protobuf:"bytes,2,opt,name=format" json:"format,omitempty"`
|
||||
Layers []*PostAncestryRequest_PostLayer `protobuf:"bytes,3,rep,name=layers" json:"layers,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PostAncestryRequest) Reset() { *m = PostAncestryRequest{} }
|
||||
func (m *PostAncestryRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PostAncestryRequest) ProtoMessage() {}
|
||||
func (*PostAncestryRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
||||
|
||||
func (m *PostAncestryRequest) GetAncestryName() string {
|
||||
if m != nil {
|
||||
return m.AncestryName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PostAncestryRequest) GetFormat() string {
|
||||
if m != nil {
|
||||
return m.Format
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PostAncestryRequest) GetLayers() []*PostAncestryRequest_PostLayer {
|
||||
if m != nil {
|
||||
return m.Layers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PostAncestryRequest_PostLayer struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
|
||||
Headers map[string]string `protobuf:"bytes,3,rep,name=headers" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||
}
|
||||
|
||||
func (m *PostAncestryRequest_PostLayer) Reset() { *m = PostAncestryRequest_PostLayer{} }
|
||||
func (m *PostAncestryRequest_PostLayer) String() string { return proto.CompactTextString(m) }
|
||||
func (*PostAncestryRequest_PostLayer) ProtoMessage() {}
|
||||
func (*PostAncestryRequest_PostLayer) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor0, []int{8, 0}
|
||||
}
|
||||
|
||||
func (m *PostAncestryRequest_PostLayer) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PostAncestryRequest_PostLayer) GetPath() string {
|
||||
if m != nil {
|
||||
return m.Path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PostAncestryRequest_PostLayer) GetHeaders() map[string]string {
|
||||
if m != nil {
|
||||
return m.Headers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PostAncestryResponse struct {
|
||||
EngineVersion int32 `protobuf:"varint,1,opt,name=engine_version,json=engineVersion" json:"engine_version,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PostAncestryResponse) Reset() { *m = PostAncestryResponse{} }
|
||||
func (m *PostAncestryResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*PostAncestryResponse) ProtoMessage() {}
|
||||
func (*PostAncestryResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
|
||||
|
||||
func (m *PostAncestryResponse) GetEngineVersion() int32 {
|
||||
if m != nil {
|
||||
return m.EngineVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetAncestryRequest struct {
|
||||
AncestryName string `protobuf:"bytes,1,opt,name=ancestry_name,json=ancestryName" json:"ancestry_name,omitempty"`
|
||||
WithVulnerabilities bool `protobuf:"varint,2,opt,name=with_vulnerabilities,json=withVulnerabilities" json:"with_vulnerabilities,omitempty"`
|
||||
WithFeatures bool `protobuf:"varint,3,opt,name=with_features,json=withFeatures" json:"with_features,omitempty"`
|
||||
}
|
||||
|
||||
func (m *GetAncestryRequest) Reset() { *m = GetAncestryRequest{} }
|
||||
func (m *GetAncestryRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetAncestryRequest) ProtoMessage() {}
|
||||
func (*GetAncestryRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
|
||||
|
||||
func (m *GetAncestryRequest) GetAncestryName() string {
|
||||
if m != nil {
|
||||
return m.AncestryName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GetAncestryRequest) GetWithVulnerabilities() bool {
|
||||
if m != nil {
|
||||
return m.WithVulnerabilities
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *GetAncestryRequest) GetWithFeatures() bool {
|
||||
if m != nil {
|
||||
return m.WithFeatures
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type GetAncestryResponse struct {
|
||||
Ancestry *Ancestry `protobuf:"bytes,1,opt,name=ancestry" json:"ancestry,omitempty"`
|
||||
Features []*Feature `protobuf:"bytes,2,rep,name=features" json:"features,omitempty"`
|
||||
}
|
||||
|
||||
func (m *GetAncestryResponse) Reset() { *m = GetAncestryResponse{} }
|
||||
func (m *GetAncestryResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetAncestryResponse) ProtoMessage() {}
|
||||
func (*GetAncestryResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
|
||||
|
||||
func (m *GetAncestryResponse) GetAncestry() *Ancestry {
|
||||
if m != nil {
|
||||
return m.Ancestry
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GetAncestryResponse) GetFeatures() []*Feature {
|
||||
if m != nil {
|
||||
return m.Features
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetNotificationRequest struct {
|
||||
Page string `protobuf:"bytes,1,opt,name=page" json:"page,omitempty"`
|
||||
Limit int32 `protobuf:"varint,2,opt,name=limit" json:"limit,omitempty"`
|
||||
Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *GetNotificationRequest) Reset() { *m = GetNotificationRequest{} }
|
||||
func (m *GetNotificationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetNotificationRequest) ProtoMessage() {}
|
||||
func (*GetNotificationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
|
||||
|
||||
func (m *GetNotificationRequest) GetPage() string {
|
||||
if m != nil {
|
||||
return m.Page
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GetNotificationRequest) GetLimit() int32 {
|
||||
if m != nil {
|
||||
return m.Limit
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *GetNotificationRequest) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetNotificationResponse struct {
|
||||
Notification *Notification `protobuf:"bytes,1,opt,name=notification" json:"notification,omitempty"`
|
||||
}
|
||||
|
||||
func (m *GetNotificationResponse) Reset() { *m = GetNotificationResponse{} }
|
||||
func (m *GetNotificationResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetNotificationResponse) ProtoMessage() {}
|
||||
func (*GetNotificationResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
|
||||
|
||||
func (m *GetNotificationResponse) GetNotification() *Notification {
|
||||
if m != nil {
|
||||
return m.Notification
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeleteNotificationRequest struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DeleteNotificationRequest) Reset() { *m = DeleteNotificationRequest{} }
|
||||
func (m *DeleteNotificationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteNotificationRequest) ProtoMessage() {}
|
||||
func (*DeleteNotificationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
|
||||
|
||||
func (m *DeleteNotificationRequest) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Vulnerability)(nil), "clairpb.Vulnerability")
|
||||
proto.RegisterType((*Feature)(nil), "clairpb.Feature")
|
||||
proto.RegisterType((*Ancestry)(nil), "clairpb.Ancestry")
|
||||
proto.RegisterType((*LayersIntroducingVulnerabilty)(nil), "clairpb.LayersIntroducingVulnerabilty")
|
||||
proto.RegisterType((*OrderedLayerName)(nil), "clairpb.OrderedLayerName")
|
||||
proto.RegisterType((*Layer)(nil), "clairpb.Layer")
|
||||
proto.RegisterType((*Notification)(nil), "clairpb.Notification")
|
||||
proto.RegisterType((*Page)(nil), "clairpb.Page")
|
||||
proto.RegisterType((*PostAncestryRequest)(nil), "clairpb.PostAncestryRequest")
|
||||
proto.RegisterType((*PostAncestryRequest_PostLayer)(nil), "clairpb.PostAncestryRequest.PostLayer")
|
||||
proto.RegisterType((*PostAncestryResponse)(nil), "clairpb.PostAncestryResponse")
|
||||
proto.RegisterType((*GetAncestryRequest)(nil), "clairpb.GetAncestryRequest")
|
||||
proto.RegisterType((*GetAncestryResponse)(nil), "clairpb.GetAncestryResponse")
|
||||
proto.RegisterType((*GetNotificationRequest)(nil), "clairpb.GetNotificationRequest")
|
||||
proto.RegisterType((*GetNotificationResponse)(nil), "clairpb.GetNotificationResponse")
|
||||
proto.RegisterType((*DeleteNotificationRequest)(nil), "clairpb.DeleteNotificationRequest")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for AncestryService service
|
||||
|
||||
type AncestryServiceClient interface {
|
||||
PostAncestry(ctx context.Context, in *PostAncestryRequest, opts ...grpc.CallOption) (*PostAncestryResponse, error)
|
||||
GetAncestry(ctx context.Context, in *GetAncestryRequest, opts ...grpc.CallOption) (*GetAncestryResponse, error)
|
||||
}
|
||||
|
||||
type ancestryServiceClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewAncestryServiceClient(cc *grpc.ClientConn) AncestryServiceClient {
|
||||
return &ancestryServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *ancestryServiceClient) PostAncestry(ctx context.Context, in *PostAncestryRequest, opts ...grpc.CallOption) (*PostAncestryResponse, error) {
|
||||
out := new(PostAncestryResponse)
|
||||
err := grpc.Invoke(ctx, "/clairpb.AncestryService/PostAncestry", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *ancestryServiceClient) GetAncestry(ctx context.Context, in *GetAncestryRequest, opts ...grpc.CallOption) (*GetAncestryResponse, error) {
|
||||
out := new(GetAncestryResponse)
|
||||
err := grpc.Invoke(ctx, "/clairpb.AncestryService/GetAncestry", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for AncestryService service
|
||||
|
||||
type AncestryServiceServer interface {
|
||||
PostAncestry(context.Context, *PostAncestryRequest) (*PostAncestryResponse, error)
|
||||
GetAncestry(context.Context, *GetAncestryRequest) (*GetAncestryResponse, error)
|
||||
}
|
||||
|
||||
func RegisterAncestryServiceServer(s *grpc.Server, srv AncestryServiceServer) {
|
||||
s.RegisterService(&_AncestryService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _AncestryService_PostAncestry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(PostAncestryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AncestryServiceServer).PostAncestry(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/clairpb.AncestryService/PostAncestry",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AncestryServiceServer).PostAncestry(ctx, req.(*PostAncestryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _AncestryService_GetAncestry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetAncestryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AncestryServiceServer).GetAncestry(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/clairpb.AncestryService/GetAncestry",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AncestryServiceServer).GetAncestry(ctx, req.(*GetAncestryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _AncestryService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "clairpb.AncestryService",
|
||||
HandlerType: (*AncestryServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "PostAncestry",
|
||||
Handler: _AncestryService_PostAncestry_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetAncestry",
|
||||
Handler: _AncestryService_GetAncestry_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "clair.proto",
|
||||
}
|
||||
|
||||
// Client API for NotificationService service
|
||||
|
||||
type NotificationServiceClient interface {
|
||||
GetNotification(ctx context.Context, in *GetNotificationRequest, opts ...grpc.CallOption) (*GetNotificationResponse, error)
|
||||
DeleteNotification(ctx context.Context, in *DeleteNotificationRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error)
|
||||
}
|
||||
|
||||
type notificationServiceClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewNotificationServiceClient(cc *grpc.ClientConn) NotificationServiceClient {
|
||||
return ¬ificationServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *notificationServiceClient) GetNotification(ctx context.Context, in *GetNotificationRequest, opts ...grpc.CallOption) (*GetNotificationResponse, error) {
|
||||
out := new(GetNotificationResponse)
|
||||
err := grpc.Invoke(ctx, "/clairpb.NotificationService/GetNotification", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *notificationServiceClient) DeleteNotification(ctx context.Context, in *DeleteNotificationRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) {
|
||||
out := new(google_protobuf1.Empty)
|
||||
err := grpc.Invoke(ctx, "/clairpb.NotificationService/DeleteNotification", in, out, c.cc, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for NotificationService service
|
||||
|
||||
type NotificationServiceServer interface {
|
||||
GetNotification(context.Context, *GetNotificationRequest) (*GetNotificationResponse, error)
|
||||
DeleteNotification(context.Context, *DeleteNotificationRequest) (*google_protobuf1.Empty, error)
|
||||
}
|
||||
|
||||
func RegisterNotificationServiceServer(s *grpc.Server, srv NotificationServiceServer) {
|
||||
s.RegisterService(&_NotificationService_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _NotificationService_GetNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetNotificationRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(NotificationServiceServer).GetNotification(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/clairpb.NotificationService/GetNotification",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(NotificationServiceServer).GetNotification(ctx, req.(*GetNotificationRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _NotificationService_DeleteNotification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(DeleteNotificationRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(NotificationServiceServer).DeleteNotification(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/clairpb.NotificationService/DeleteNotification",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(NotificationServiceServer).DeleteNotification(ctx, req.(*DeleteNotificationRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _NotificationService_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "clairpb.NotificationService",
|
||||
HandlerType: (*NotificationServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetNotification",
|
||||
Handler: _NotificationService_GetNotification_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "DeleteNotification",
|
||||
Handler: _NotificationService_DeleteNotification_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "clair.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("clair.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 1042 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x6e, 0x1b, 0x45,
|
||||
0x14, 0xd6, 0xda, 0x71, 0x6c, 0x1f, 0xdb, 0x49, 0x3a, 0x49, 0xd3, 0x8d, 0x93, 0x88, 0x74, 0x11,
|
||||
0xa5, 0xaa, 0xc0, 0x56, 0xd3, 0x9b, 0x12, 0x01, 0x82, 0xa8, 0x6d, 0xa8, 0x04, 0xa5, 0x5a, 0xaa,
|
||||
0x5c, 0x70, 0x63, 0x4d, 0xbc, 0x27, 0xce, 0x28, 0xeb, 0x59, 0xb3, 0x3b, 0x76, 0x62, 0x55, 0xdc,
|
||||
0xf0, 0x04, 0x54, 0x3c, 0x06, 0x2f, 0xc0, 0x15, 0x2f, 0xd1, 0x27, 0x00, 0xf1, 0x16, 0xdc, 0xa0,
|
||||
0xf9, 0xf5, 0xae, 0x63, 0x23, 0x7e, 0xae, 0x3c, 0xe7, 0x7c, 0xe7, 0xe7, 0x3b, 0x3f, 0x33, 0x5e,
|
||||
0x68, 0xf4, 0x63, 0xca, 0xd2, 0xce, 0x28, 0x4d, 0x44, 0x42, 0xaa, 0x4a, 0x18, 0x9d, 0xb5, 0xf7,
|
||||
0x06, 0x49, 0x32, 0x88, 0xb1, 0x4b, 0x47, 0xac, 0x4b, 0x39, 0x4f, 0x04, 0x15, 0x2c, 0xe1, 0x99,
|
||||
0x36, 0x6b, 0xef, 0x1a, 0x54, 0x49, 0x67, 0xe3, 0xf3, 0x2e, 0x0e, 0x47, 0x62, 0xaa, 0xc1, 0xe0,
|
||||
0x4d, 0x09, 0x5a, 0xa7, 0xe3, 0x98, 0x63, 0x4a, 0xcf, 0x58, 0xcc, 0xc4, 0x94, 0x10, 0x58, 0xe1,
|
||||
0x74, 0x88, 0xbe, 0x77, 0xe0, 0xdd, 0xaf, 0x87, 0xea, 0x4c, 0xde, 0x83, 0x35, 0xf9, 0x9b, 0x8d,
|
||||
0x68, 0x1f, 0x7b, 0x0a, 0x2d, 0x29, 0xb4, 0xe5, 0xb4, 0x2f, 0xa4, 0xd9, 0x01, 0x34, 0x22, 0xcc,
|
||||
0xfa, 0x29, 0x1b, 0xc9, 0xfc, 0x7e, 0x59, 0xd9, 0xe4, 0x55, 0x32, 0x78, 0xcc, 0xf8, 0xa5, 0xbf,
|
||||
0xa2, 0x83, 0xcb, 0x33, 0x69, 0x43, 0x2d, 0xc3, 0x09, 0xa6, 0x4c, 0x4c, 0xfd, 0x8a, 0xd2, 0x3b,
|
||||
0x59, 0x62, 0x43, 0x14, 0x34, 0xa2, 0x82, 0xfa, 0xab, 0x1a, 0xb3, 0x32, 0xd9, 0x81, 0xda, 0x39,
|
||||
0xbb, 0xc6, 0xa8, 0x77, 0x36, 0xf5, 0xab, 0x0a, 0xab, 0x2a, 0xf9, 0x78, 0x4a, 0x3e, 0x86, 0x5b,
|
||||
0x1a, 0x62, 0xbc, 0x77, 0x8e, 0x54, 0x8c, 0x53, 0xcc, 0xfc, 0xda, 0x41, 0xf9, 0x7e, 0xe3, 0x70,
|
||||
0xa3, 0x63, 0xba, 0xd6, 0x79, 0xa6, 0x81, 0x70, 0x5d, 0x99, 0x3e, 0xe7, 0x46, 0xce, 0x82, 0xdf,
|
||||
0x3d, 0xa8, 0x1a, 0xe1, 0xff, 0x74, 0xc3, 0x87, 0xea, 0x04, 0xd3, 0x6c, 0xd6, 0x09, 0x2b, 0xca,
|
||||
0x00, 0xe6, 0xd8, 0x3b, 0x4f, 0xd2, 0x21, 0x15, 0xa6, 0x1f, 0x2d, 0xa3, 0x7d, 0xa6, 0x94, 0xb2,
|
||||
0x40, 0x1a, 0x45, 0xba, 0x40, 0xdd, 0x98, 0xaa, 0x92, 0x8f, 0xa7, 0xe4, 0x33, 0x58, 0x9f, 0xe4,
|
||||
0xa6, 0xc6, 0x30, 0xf3, 0x57, 0x55, 0x79, 0xdb, 0xae, 0xbc, 0xc2, 0x54, 0xc3, 0x79, 0xf3, 0x60,
|
||||
0x08, 0xb5, 0xcf, 0x79, 0x1f, 0x33, 0x91, 0x2e, 0x1d, 0x39, 0xf2, 0x01, 0xe3, 0xd8, 0xb3, 0x45,
|
||||
0xc8, 0x22, 0x2b, 0x61, 0x4b, 0x6b, 0x4f, 0x4d, 0x29, 0xf7, 0x60, 0x35, 0xa6, 0x53, 0x4c, 0x33,
|
||||
0xbf, 0xac, 0xf2, 0xaf, 0xb9, 0xfc, 0x5f, 0x4a, 0x75, 0x68, 0xd0, 0xe0, 0x47, 0x0f, 0xf6, 0x95,
|
||||
0x26, 0x7b, 0xce, 0x45, 0x9a, 0x44, 0xe3, 0x3e, 0xe3, 0x83, 0x19, 0x45, 0x21, 0x67, 0xd6, 0xca,
|
||||
0x73, 0x9c, 0x2a, 0x36, 0xcb, 0x0b, 0x2a, 0x1a, 0x93, 0x87, 0x8e, 0x47, 0x49, 0xf1, 0xd8, 0x71,
|
||||
0x6e, 0x5f, 0xa7, 0x11, 0xa6, 0x18, 0xa9, 0xe4, 0x72, 0x2e, 0x8e, 0xd2, 0x09, 0x6c, 0xcc, 0x63,
|
||||
0x64, 0x0b, 0x2a, 0x8c, 0x47, 0x78, 0xad, 0x92, 0x57, 0x42, 0x2d, 0x90, 0x7d, 0x00, 0xe5, 0x93,
|
||||
0x1f, 0x76, 0x3d, 0xb6, 0x4e, 0xc1, 0x13, 0xa8, 0xa8, 0x08, 0x0b, 0xfb, 0xf8, 0x3e, 0xac, 0x17,
|
||||
0x97, 0x45, 0x33, 0xac, 0x87, 0x6b, 0x85, 0x6d, 0xc9, 0x82, 0x9f, 0x3d, 0x68, 0xbe, 0x48, 0x04,
|
||||
0x3b, 0x67, 0x7d, 0x6a, 0xef, 0xca, 0x8d, 0x68, 0x3e, 0x54, 0xfb, 0x29, 0x52, 0x81, 0x91, 0xa1,
|
||||
0x61, 0x45, 0x79, 0x53, 0xb8, 0xf2, 0xc6, 0xc8, 0xac, 0x9b, 0x93, 0xa5, 0x57, 0x84, 0x31, 0x4a,
|
||||
0x2f, 0xbd, 0x68, 0x56, 0x94, 0xf5, 0xc6, 0x6c, 0xc8, 0x84, 0xda, 0xaf, 0x4a, 0xa8, 0x05, 0x72,
|
||||
0x17, 0x56, 0x46, 0x74, 0x80, 0xea, 0xc6, 0x35, 0x0e, 0x5b, 0xae, 0x95, 0x2f, 0xe9, 0x00, 0x43,
|
||||
0x05, 0x05, 0xbf, 0x78, 0xb0, 0x22, 0x45, 0xd9, 0x1b, 0x71, 0xc1, 0xb2, 0x9e, 0x48, 0x2e, 0x91,
|
||||
0x1b, 0xae, 0x75, 0xa9, 0x79, 0x25, 0x15, 0x12, 0xe6, 0x78, 0x2d, 0x0c, 0x6c, 0x5a, 0x27, 0x35,
|
||||
0x1a, 0x7e, 0x0c, 0xe5, 0x24, 0xd6, 0x84, 0x1b, 0x87, 0xf7, 0x8a, 0xbb, 0xb3, 0x6c, 0x53, 0x42,
|
||||
0xe9, 0x22, 0x3d, 0x39, 0x5e, 0xa9, 0x7a, 0xfe, 0x85, 0x27, 0xc7, 0xab, 0xe0, 0x6d, 0x09, 0x36,
|
||||
0x5f, 0x26, 0x99, 0xb0, 0xeb, 0x1f, 0xe2, 0x77, 0x63, 0xcc, 0x04, 0x79, 0x17, 0x5a, 0xd4, 0xa8,
|
||||
0x7a, 0xb9, 0xc6, 0x37, 0xad, 0x52, 0x2d, 0xc8, 0x36, 0xac, 0x9a, 0x2b, 0xab, 0x6b, 0x31, 0x12,
|
||||
0xf9, 0x74, 0xee, 0x1e, 0xcc, 0x18, 0x2d, 0x48, 0xa5, 0x74, 0x85, 0xfb, 0xd1, 0xfe, 0xd5, 0x83,
|
||||
0xba, 0xd3, 0x2e, 0x1c, 0x3d, 0x91, 0x43, 0x11, 0x17, 0x26, 0xaf, 0x3a, 0x93, 0xaf, 0xa0, 0x7a,
|
||||
0x81, 0x34, 0x9a, 0xa5, 0x7d, 0xf4, 0xcf, 0xd2, 0x76, 0xbe, 0xd0, 0x5e, 0x4f, 0xb9, 0x44, 0x6d,
|
||||
0x8c, 0xf6, 0x11, 0x34, 0xf3, 0x00, 0xd9, 0x80, 0xf2, 0x25, 0x4e, 0x0d, 0x0b, 0x79, 0x94, 0xfb,
|
||||
0x32, 0xa1, 0xf1, 0xd8, 0x5e, 0x02, 0x2d, 0x1c, 0x95, 0x1e, 0x7b, 0xc1, 0x27, 0xb0, 0x55, 0x4c,
|
||||
0x99, 0x8d, 0x12, 0x9e, 0x2d, 0x7a, 0x47, 0xbc, 0x05, 0xef, 0x48, 0xf0, 0xc6, 0x03, 0x72, 0x82,
|
||||
0xff, 0x6d, 0x26, 0x0f, 0x61, 0xeb, 0x8a, 0x89, 0x8b, 0xde, 0xfc, 0x8b, 0x28, 0x39, 0xd6, 0xc2,
|
||||
0x4d, 0x89, 0x9d, 0x16, 0x21, 0x19, 0x57, 0xb9, 0xb8, 0x3f, 0x87, 0xb2, 0xb2, 0x6d, 0x4a, 0xa5,
|
||||
0xfb, 0x1f, 0x48, 0x61, 0xb3, 0x40, 0xc9, 0x54, 0xf4, 0x21, 0xd4, 0x6c, 0x7a, 0xf3, 0x46, 0xdd,
|
||||
0x72, 0x5d, 0x77, 0xc6, 0xce, 0x84, 0x7c, 0x00, 0x35, 0x97, 0xa5, 0xb4, 0xe4, 0x2f, 0xc8, 0x59,
|
||||
0x04, 0xa7, 0xb0, 0x7d, 0x82, 0x22, 0xff, 0x0e, 0xd8, 0x56, 0x10, 0x73, 0x29, 0x3d, 0x3b, 0xff,
|
||||
0x01, 0xce, 0xae, 0x6f, 0x29, 0x7f, 0x7d, 0xed, 0xf6, 0x94, 0x67, 0xdb, 0x13, 0xbc, 0x82, 0x3b,
|
||||
0x37, 0xe2, 0x9a, 0x7a, 0x3e, 0x82, 0x26, 0xcf, 0xe9, 0x4d, 0x4d, 0xb7, 0x1d, 0xc9, 0x82, 0x53,
|
||||
0xc1, 0x34, 0xe8, 0xc2, 0xce, 0x13, 0xf5, 0x92, 0x2c, 0x21, 0x3c, 0xbf, 0xc4, 0x87, 0xbf, 0x79,
|
||||
0xb0, 0x6e, 0x7b, 0xf4, 0x0d, 0xa6, 0x13, 0xd6, 0x47, 0x42, 0xa1, 0x99, 0xdf, 0x1c, 0xb2, 0xf7,
|
||||
0x77, 0x3b, 0xdc, 0xde, 0x5f, 0x82, 0xea, 0x62, 0x82, 0xad, 0x1f, 0xde, 0xfe, 0xf1, 0x53, 0x69,
|
||||
0x2d, 0xa8, 0x77, 0xed, 0x00, 0x8e, 0xbc, 0x07, 0xe4, 0x12, 0x1a, 0xb9, 0x49, 0x92, 0x5d, 0x17,
|
||||
0xe3, 0xe6, 0xca, 0xb5, 0xf7, 0x16, 0x83, 0x26, 0xfe, 0x5d, 0x15, 0x7f, 0x97, 0xec, 0xb8, 0xf8,
|
||||
0xdd, 0xd7, 0x85, 0x0d, 0xfd, 0xfe, 0xf0, 0x4f, 0x0f, 0x36, 0xf3, 0xfd, 0xb0, 0x75, 0x66, 0xb0,
|
||||
0x3e, 0x37, 0x02, 0xf2, 0x4e, 0x3e, 0xd7, 0x82, 0x1e, 0xb6, 0x0f, 0x96, 0x1b, 0x18, 0x42, 0xfb,
|
||||
0x8a, 0xd0, 0x1d, 0x72, 0xbb, 0x9b, 0x9f, 0x4c, 0xd6, 0x7d, 0xad, 0xc8, 0x90, 0x04, 0xc8, 0xcd,
|
||||
0x09, 0x91, 0xc0, 0x85, 0x5d, 0x3a, 0xbe, 0xf6, 0x76, 0x47, 0x7f, 0x37, 0x76, 0xec, 0x77, 0x63,
|
||||
0xe7, 0xa9, 0xfc, 0x6e, 0xb4, 0x09, 0x1f, 0x2c, 0x4e, 0x78, 0x5c, 0xff, 0xd6, 0x7e, 0x96, 0x9e,
|
||||
0xad, 0x2a, 0xcf, 0x47, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x9c, 0x1d, 0xc4, 0xb5, 0x0a,
|
||||
0x00, 0x00,
|
||||
}
|
346
api/v2/clairpb/clair.pb.gw.go
Normal file
346
api/v2/clairpb/clair.pb.gw.go
Normal file
@ -0,0 +1,346 @@
|
||||
// Code generated by protoc-gen-grpc-gateway
|
||||
// source: clair.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package clairpb is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package clairpb
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
|
||||
func request_AncestryService_PostAncestry_0(ctx context.Context, marshaler runtime.Marshaler, client AncestryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq PostAncestryRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.PostAncestry(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_AncestryService_GetAncestry_0 = &utilities.DoubleArray{Encoding: map[string]int{"ancestry_name": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
|
||||
)
|
||||
|
||||
func request_AncestryService_GetAncestry_0(ctx context.Context, marshaler runtime.Marshaler, client AncestryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetAncestryRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["ancestry_name"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "ancestry_name")
|
||||
}
|
||||
|
||||
protoReq.AncestryName, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_AncestryService_GetAncestry_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GetAncestry(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_NotificationService_GetNotification_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
|
||||
)
|
||||
|
||||
func request_NotificationService_GetNotification_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetNotificationRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["name"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
|
||||
}
|
||||
|
||||
protoReq.Name, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_NotificationService_GetNotification_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GetNotification(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_NotificationService_DeleteNotification_0(ctx context.Context, marshaler runtime.Marshaler, client NotificationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq DeleteNotificationRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["name"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
|
||||
}
|
||||
|
||||
protoReq.Name, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
|
||||
msg, err := client.DeleteNotification(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterAncestryServiceHandlerFromEndpoint is same as RegisterAncestryServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterAncestryServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterAncestryServiceHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterAncestryServiceHandler registers the http handlers for service AncestryService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterAncestryServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
client := NewAncestryServiceClient(conn)
|
||||
|
||||
mux.Handle("POST", pattern_AncestryService_PostAncestry_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_AncestryService_PostAncestry_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AncestryService_PostAncestry_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_AncestryService_GetAncestry_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_AncestryService_GetAncestry_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AncestryService_GetAncestry_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_AncestryService_PostAncestry_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"ancestry"}, ""))
|
||||
|
||||
pattern_AncestryService_GetAncestry_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"ancestry", "ancestry_name"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_AncestryService_PostAncestry_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_AncestryService_GetAncestry_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
||||
// RegisterNotificationServiceHandlerFromEndpoint is same as RegisterNotificationServiceHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterNotificationServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterNotificationServiceHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterNotificationServiceHandler registers the http handlers for service NotificationService to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterNotificationServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
client := NewNotificationServiceClient(conn)
|
||||
|
||||
mux.Handle("GET", pattern_NotificationService_GetNotification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_NotificationService_GetNotification_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_NotificationService_GetNotification_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_NotificationService_DeleteNotification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_NotificationService_DeleteNotification_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_NotificationService_DeleteNotification_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_NotificationService_GetNotification_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"notifications", "name"}, ""))
|
||||
|
||||
pattern_NotificationService_DeleteNotification_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"notifications", "name"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_NotificationService_GetNotification_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_NotificationService_DeleteNotification_0 = runtime.ForwardResponseMessage
|
||||
)
|
149
api/v2/clairpb/clair.proto
Normal file
149
api/v2/clairpb/clair.proto
Normal file
@ -0,0 +1,149 @@
|
||||
// Copyright 2017 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
option go_package = "clairpb";
|
||||
|
||||
package clairpb;
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
message Vulnerability {
|
||||
string name = 1;
|
||||
string namespace_name = 2;
|
||||
string description = 3;
|
||||
string link = 4;
|
||||
string severity = 5;
|
||||
string metadata = 6;
|
||||
string fixed_by = 7;
|
||||
repeated Feature fixed_in_features = 8;
|
||||
}
|
||||
|
||||
message Feature {
|
||||
string name = 1;
|
||||
string namespace_name = 2;
|
||||
string version = 3;
|
||||
string version_format = 4;
|
||||
string added_by = 5;
|
||||
repeated Vulnerability vulnerabilities = 6;
|
||||
}
|
||||
|
||||
message Ancestry {
|
||||
string name = 1;
|
||||
int32 engine_version = 2;
|
||||
repeated Layer layers = 3;
|
||||
}
|
||||
|
||||
message LayersIntroducingVulnerabilty {
|
||||
Vulnerability vulnerability = 1;
|
||||
repeated OrderedLayerName layers = 2;
|
||||
}
|
||||
|
||||
message OrderedLayerName {
|
||||
int32 index = 1;
|
||||
string layer_name = 2;
|
||||
}
|
||||
|
||||
message Layer {
|
||||
string name = 1;
|
||||
repeated string namespace_names = 2;
|
||||
}
|
||||
|
||||
message Notification {
|
||||
string name = 1;
|
||||
string created = 2;
|
||||
string notified = 3;
|
||||
string deleted = 4;
|
||||
int32 limit = 5;
|
||||
Page page = 6;
|
||||
}
|
||||
|
||||
message Page {
|
||||
string this_token = 1;
|
||||
string next_token = 2;
|
||||
LayersIntroducingVulnerabilty old = 3;
|
||||
LayersIntroducingVulnerabilty new = 4;
|
||||
}
|
||||
|
||||
|
||||
message PostAncestryRequest {
|
||||
message PostLayer {
|
||||
string name = 1;
|
||||
string path = 2;
|
||||
map<string, string> headers = 3;
|
||||
}
|
||||
string ancestry_name = 1;
|
||||
string format = 2;
|
||||
repeated PostLayer layers = 3;
|
||||
}
|
||||
|
||||
message PostAncestryResponse {
|
||||
int32 engine_version = 1;
|
||||
}
|
||||
|
||||
message GetAncestryRequest {
|
||||
string ancestry_name = 1;
|
||||
bool with_vulnerabilities = 2;
|
||||
bool with_features = 3;
|
||||
}
|
||||
|
||||
message GetAncestryResponse {
|
||||
Ancestry ancestry = 1;
|
||||
repeated Feature features = 2;
|
||||
}
|
||||
|
||||
message GetNotificationRequest {
|
||||
string page = 1;
|
||||
int32 limit = 2;
|
||||
string name = 3;
|
||||
}
|
||||
|
||||
message GetNotificationResponse {
|
||||
Notification notification = 1;
|
||||
}
|
||||
|
||||
message DeleteNotificationRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
service AncestryService{
|
||||
rpc PostAncestry(PostAncestryRequest) returns (PostAncestryResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/ancestry"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetAncestry(GetAncestryRequest) returns (GetAncestryResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/ancestry/{ancestry_name}"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
service NotificationService{
|
||||
rpc GetNotification(GetNotificationRequest) returns (GetNotificationResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/notifications/{name}"
|
||||
};
|
||||
}
|
||||
|
||||
rpc DeleteNotification(DeleteNotificationRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
delete: "/notifications/{name}"
|
||||
};
|
||||
}
|
||||
}
|
371
api/v2/clairpb/clair.swagger.json
Normal file
371
api/v2/clairpb/clair.swagger.json
Normal file
@ -0,0 +1,371 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "clair.proto",
|
||||
"version": "version not set"
|
||||
},
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"paths": {
|
||||
"/ancestry": {
|
||||
"post": {
|
||||
"operationId": "PostAncestry",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/clairpbPostAncestryResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/clairpbPostAncestryRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"AncestryService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/ancestry/{ancestry_name}": {
|
||||
"get": {
|
||||
"operationId": "GetAncestry",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/clairpbGetAncestryResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "ancestry_name",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "with_vulnerabilities",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "with_features",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"AncestryService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/notifications/{name}": {
|
||||
"get": {
|
||||
"operationId": "GetNotification",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/clairpbGetNotificationResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "page",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"NotificationService"
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"operationId": "DeleteNotification",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/protobufEmpty"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "name",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"NotificationService"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"PostAncestryRequestPostLayer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"headers": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbAncestry": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"engine_version": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"layers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/clairpbLayer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbFeature": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"namespace_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"version_format": {
|
||||
"type": "string"
|
||||
},
|
||||
"added_by": {
|
||||
"type": "string"
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/clairpbVulnerability"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbGetAncestryResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ancestry": {
|
||||
"$ref": "#/definitions/clairpbAncestry"
|
||||
},
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/clairpbFeature"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbGetNotificationResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"notification": {
|
||||
"$ref": "#/definitions/clairpbNotification"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbLayer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"namespace_names": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbLayersIntroducingVulnerabilty": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vulnerability": {
|
||||
"$ref": "#/definitions/clairpbVulnerability"
|
||||
},
|
||||
"layers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/clairpbOrderedLayerName"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbNotification": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"created": {
|
||||
"type": "string"
|
||||
},
|
||||
"notified": {
|
||||
"type": "string"
|
||||
},
|
||||
"deleted": {
|
||||
"type": "string"
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"page": {
|
||||
"$ref": "#/definitions/clairpbPage"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbOrderedLayerName": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"index": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"layer_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbPage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"this_token": {
|
||||
"type": "string"
|
||||
},
|
||||
"next_token": {
|
||||
"type": "string"
|
||||
},
|
||||
"old": {
|
||||
"$ref": "#/definitions/clairpbLayersIntroducingVulnerabilty"
|
||||
},
|
||||
"new": {
|
||||
"$ref": "#/definitions/clairpbLayersIntroducingVulnerabilty"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbPostAncestryRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ancestry_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
},
|
||||
"layers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PostAncestryRequestPostLayer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbPostAncestryResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"engine_version": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"clairpbVulnerability": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"namespace_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"link": {
|
||||
"type": "string"
|
||||
},
|
||||
"severity": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string"
|
||||
},
|
||||
"fixed_by": {
|
||||
"type": "string"
|
||||
},
|
||||
"fixed_in_features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/clairpbFeature"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"protobufEmpty": {
|
||||
"type": "object",
|
||||
"description": "service Foo {\n rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);\n }\n\nThe JSON representation for `Empty` is empty JSON object `{}`.",
|
||||
"title": "A generic empty message that you can re-use to avoid defining duplicated\nempty messages in your APIs. A typical example is to use it as the request\nor the response type of an API method. For instance:"
|
||||
}
|
||||
}
|
||||
}
|
165
api/v2/clairpb/convert.go
Normal file
165
api/v2/clairpb/convert.go
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2017 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package clairpb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/clair/api/token"
|
||||
"github.com/coreos/clair/database"
|
||||
"github.com/coreos/clair/ext/versionfmt"
|
||||
)
|
||||
|
||||
func NotificationFromDatabaseModel(dbNotification database.VulnerabilityNotification, limit int, pageToken string, nextPage database.VulnerabilityNotificationPageNumber, key string) (*Notification, error) {
|
||||
var oldVuln *LayersIntroducingVulnerabilty
|
||||
if dbNotification.OldVulnerability != nil {
|
||||
v, err := LayersIntroducingVulnerabiltyFromDatabaseModel(*dbNotification.OldVulnerability)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oldVuln = v
|
||||
}
|
||||
|
||||
var newVuln *LayersIntroducingVulnerabilty
|
||||
if dbNotification.NewVulnerability != nil {
|
||||
v, err := LayersIntroducingVulnerabiltyFromDatabaseModel(*dbNotification.NewVulnerability)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newVuln = v
|
||||
}
|
||||
|
||||
var nextPageStr string
|
||||
if nextPage != database.NoVulnerabilityNotificationPage {
|
||||
nextPageBytes, _ := token.Marshal(nextPage, key)
|
||||
nextPageStr = string(nextPageBytes)
|
||||
}
|
||||
|
||||
var created, notified, deleted string
|
||||
if !dbNotification.Created.IsZero() {
|
||||
created = fmt.Sprintf("%d", dbNotification.Created.Unix())
|
||||
}
|
||||
if !dbNotification.Notified.IsZero() {
|
||||
notified = fmt.Sprintf("%d", dbNotification.Notified.Unix())
|
||||
}
|
||||
if !dbNotification.Deleted.IsZero() {
|
||||
deleted = fmt.Sprintf("%d", dbNotification.Deleted.Unix())
|
||||
}
|
||||
|
||||
return &Notification{
|
||||
Name: dbNotification.Name,
|
||||
Created: created,
|
||||
Notified: notified,
|
||||
Deleted: deleted,
|
||||
Limit: int32(limit),
|
||||
Page: &Page{
|
||||
ThisToken: pageToken,
|
||||
NextToken: nextPageStr,
|
||||
Old: oldVuln,
|
||||
New: newVuln,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func LayersIntroducingVulnerabiltyFromDatabaseModel(dbVuln database.Vulnerability) (*LayersIntroducingVulnerabilty, error) {
|
||||
vuln, err := VulnerabilityFromDatabaseModel(dbVuln, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var orderedLayers []*OrderedLayerName
|
||||
|
||||
return &LayersIntroducingVulnerabilty{
|
||||
Vulnerability: vuln,
|
||||
Layers: orderedLayers,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func VulnerabilityFromDatabaseModel(dbVuln database.Vulnerability, withFixedIn bool) (*Vulnerability, error) {
|
||||
metaString := ""
|
||||
if dbVuln.Metadata != nil {
|
||||
metadataByte, err := json.Marshal(dbVuln.Metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metaString = string(metadataByte)
|
||||
}
|
||||
|
||||
vuln := Vulnerability{
|
||||
Name: dbVuln.Name,
|
||||
NamespaceName: dbVuln.Namespace.Name,
|
||||
Description: dbVuln.Description,
|
||||
Link: dbVuln.Link,
|
||||
Severity: string(dbVuln.Severity),
|
||||
Metadata: metaString,
|
||||
}
|
||||
|
||||
if dbVuln.FixedBy != versionfmt.MaxVersion {
|
||||
vuln.FixedBy = dbVuln.FixedBy
|
||||
}
|
||||
|
||||
if withFixedIn {
|
||||
for _, dbFeatureVersion := range dbVuln.FixedIn {
|
||||
f, err := FeatureFromDatabaseModel(dbFeatureVersion, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vuln.FixedInFeatures = append(vuln.FixedInFeatures, f)
|
||||
}
|
||||
}
|
||||
|
||||
return &vuln, nil
|
||||
}
|
||||
|
||||
func LayerFromDatabaseModel(dbLayer database.Layer) *Layer {
|
||||
layer := Layer{
|
||||
Name: dbLayer.Name,
|
||||
}
|
||||
for _, ns := range dbLayer.Namespaces {
|
||||
layer.NamespaceNames = append(layer.NamespaceNames, ns.Name)
|
||||
}
|
||||
|
||||
return &layer
|
||||
}
|
||||
|
||||
func FeatureFromDatabaseModel(fv database.FeatureVersion, withVulnerabilities bool) (*Feature, error) {
|
||||
version := fv.Version
|
||||
if version == versionfmt.MaxVersion {
|
||||
version = "None"
|
||||
}
|
||||
f := &Feature{
|
||||
Name: fv.Feature.Name,
|
||||
NamespaceName: fv.Feature.Namespace.Name,
|
||||
VersionFormat: fv.Feature.Namespace.VersionFormat,
|
||||
Version: version,
|
||||
AddedBy: fv.AddedBy.Name,
|
||||
}
|
||||
|
||||
if withVulnerabilities {
|
||||
for _, dbVuln := range fv.AffectedBy {
|
||||
// VulnerabilityFromDatabaseModel should be called without FixedIn,
|
||||
// Otherwise it might cause infinite loop
|
||||
vul, err := VulnerabilityFromDatabaseModel(dbVuln, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f.Vulnerabilities = append(f.Vulnerabilities, vul)
|
||||
}
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
256
api/v2/rpc.go
Normal file
256
api/v2/rpc.go
Normal file
@ -0,0 +1,256 @@
|
||||
// Copyright 2017 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
google_protobuf1 "github.com/golang/protobuf/ptypes/empty"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/coreos/clair"
|
||||
"github.com/coreos/clair/api/token"
|
||||
pb "github.com/coreos/clair/api/v2/clairpb"
|
||||
"github.com/coreos/clair/database"
|
||||
"github.com/coreos/clair/pkg/commonerr"
|
||||
"github.com/coreos/clair/pkg/tarutil"
|
||||
)
|
||||
|
||||
// NotificationServer implements NotificationService interface for serving RPC.
|
||||
type NotificationServer struct {
|
||||
Store database.Datastore
|
||||
PaginationKey string
|
||||
}
|
||||
|
||||
// AncestryServer implements AncestryService interface for serving RPC.
|
||||
type AncestryServer struct {
|
||||
Store database.Datastore
|
||||
}
|
||||
|
||||
// PostAncestry implements posting an ancestry via the Clair gRPC service.
|
||||
func (s *AncestryServer) PostAncestry(ctx context.Context, req *pb.PostAncestryRequest) (*pb.PostAncestryResponse, error) {
|
||||
ancestryName := req.GetAncestryName()
|
||||
if ancestryName == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "Failed to provide proper ancestry name")
|
||||
}
|
||||
|
||||
layers := req.GetLayers()
|
||||
if len(layers) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "At least one layer should be provided for an ancestry")
|
||||
}
|
||||
|
||||
var currentName, parentName, rootName string
|
||||
for i, layer := range layers {
|
||||
if layer == nil {
|
||||
err := status.Error(codes.InvalidArgument, "Failed to provide layer")
|
||||
return nil, s.rollBackOnError(err, currentName, rootName)
|
||||
}
|
||||
|
||||
// TODO(keyboardnerd): after altering the database to support ancestry,
|
||||
// we should use the ancestry name and index as key instead of
|
||||
// the amalgamation of ancestry name of index
|
||||
// Hack: layer name is [ancestryName]-[index] except the tail layer,
|
||||
// tail layer name is [ancestryName]
|
||||
if i == len(layers)-1 {
|
||||
currentName = ancestryName
|
||||
} else {
|
||||
currentName = fmt.Sprintf("%s-%d", ancestryName, i)
|
||||
}
|
||||
|
||||
// if rootName is unset, this is the first iteration over the layers and
|
||||
// the current layer is the root of the ancestry
|
||||
if rootName == "" {
|
||||
rootName = currentName
|
||||
}
|
||||
|
||||
err := clair.ProcessLayer(s.Store, req.GetFormat(), currentName, parentName, layer.GetPath(), layer.GetHeaders())
|
||||
if err != nil {
|
||||
return nil, s.rollBackOnError(err, currentName, rootName)
|
||||
}
|
||||
|
||||
// Now that the current layer is processed, set the parentName for the
|
||||
// next iteration.
|
||||
parentName = currentName
|
||||
}
|
||||
|
||||
return &pb.PostAncestryResponse{
|
||||
EngineVersion: clair.Version,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAncestry implements retrieving an ancestry via the Clair gRPC service.
|
||||
func (s *AncestryServer) GetAncestry(ctx context.Context, req *pb.GetAncestryRequest) (*pb.GetAncestryResponse, error) {
|
||||
if req.GetAncestryName() == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid get ancestry request")
|
||||
}
|
||||
|
||||
// TODO(keyboardnerd): after altering the database to support ancestry, this
|
||||
// function is iteratively querying for for r.GetIndex() th parent of the
|
||||
// requested layer until the indexed layer is found or index is out of bound
|
||||
// this is a hack and will be replaced with one query
|
||||
ancestry, features, err := s.getAncestry(req.GetAncestryName(), req.GetWithFeatures(), req.GetWithVulnerabilities())
|
||||
if err == commonerr.ErrNotFound {
|
||||
return nil, status.Error(codes.NotFound, err.Error())
|
||||
} else if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &pb.GetAncestryResponse{
|
||||
Ancestry: ancestry,
|
||||
Features: features,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetNotification implements retrieving a notification via the Clair gRPC
|
||||
// service.
|
||||
func (s *NotificationServer) GetNotification(ctx context.Context, req *pb.GetNotificationRequest) (*pb.GetNotificationResponse, error) {
|
||||
if req.GetName() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "Failed to provide notification name")
|
||||
}
|
||||
|
||||
if req.GetLimit() <= 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Failed to provide page limit")
|
||||
}
|
||||
|
||||
page := database.VulnerabilityNotificationFirstPage
|
||||
pageToken := req.GetPage()
|
||||
if pageToken != "" {
|
||||
err := token.Unmarshal(pageToken, s.PaginationKey, &page)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Invalid page format %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
pageTokenBytes, err := token.Marshal(page, s.PaginationKey)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Failed to marshal token: %s", err.Error())
|
||||
}
|
||||
pageToken = string(pageTokenBytes)
|
||||
}
|
||||
|
||||
dbNotification, nextPage, err := s.Store.GetNotification(req.GetName(), int(req.GetLimit()), page)
|
||||
if err == commonerr.ErrNotFound {
|
||||
return nil, status.Error(codes.NotFound, err.Error())
|
||||
} else if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
notification, err := pb.NotificationFromDatabaseModel(dbNotification, int(req.GetLimit()), pageToken, nextPage, s.PaginationKey)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &pb.GetNotificationResponse{Notification: notification}, nil
|
||||
}
|
||||
|
||||
// DeleteNotification implements deleting a notification via the Clair gRPC
|
||||
// service.
|
||||
func (s *NotificationServer) DeleteNotification(ctx context.Context, req *pb.DeleteNotificationRequest) (*google_protobuf1.Empty, error) {
|
||||
if req.GetName() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "Failed to provide notification name")
|
||||
}
|
||||
|
||||
err := s.Store.DeleteNotification(req.GetName())
|
||||
if err == commonerr.ErrNotFound {
|
||||
return nil, status.Error(codes.NotFound, err.Error())
|
||||
} else if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &google_protobuf1.Empty{}, nil
|
||||
}
|
||||
|
||||
// rollBackOnError handles server error and rollback whole ancestry insertion if
|
||||
// any layer failed to be inserted.
|
||||
func (s *AncestryServer) rollBackOnError(err error, currentLayerName, rootLayerName string) error {
|
||||
// if the current layer failed to be inserted and it's the root layer,
|
||||
// then the ancestry is not yet in the database.
|
||||
if currentLayerName != rootLayerName {
|
||||
errrb := s.Store.DeleteLayer(rootLayerName)
|
||||
if errrb != nil {
|
||||
return status.Errorf(codes.Internal, errrb.Error())
|
||||
}
|
||||
log.WithField("layer name", currentLayerName).Warnf("Can't process %s: roll back the ancestry", currentLayerName)
|
||||
}
|
||||
|
||||
if err == tarutil.ErrCouldNotExtract ||
|
||||
err == tarutil.ErrExtractedFileTooBig ||
|
||||
err == clair.ErrUnsupported {
|
||||
return status.Errorf(codes.InvalidArgument, "unprocessable entity %s", err.Error())
|
||||
}
|
||||
|
||||
if _, badreq := err.(*commonerr.ErrBadRequest); badreq {
|
||||
return status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
// TODO(keyboardnerd): Remove this Legacy compability code once the database is
|
||||
// revised.
|
||||
// getAncestry returns an ancestry from database by getting all parents of a
|
||||
// layer given the layer name, and the layer's feature list if
|
||||
// withFeature/withVulnerability is turned on.
|
||||
func (s *AncestryServer) getAncestry(name string, withFeature bool, withVulnerability bool) (ancestry *pb.Ancestry, features []*pb.Feature, err error) {
|
||||
var (
|
||||
layers = []*pb.Layer{}
|
||||
layer database.Layer
|
||||
)
|
||||
ancestry = &pb.Ancestry{}
|
||||
|
||||
layer, err = s.Store.FindLayer(name, withFeature, withVulnerability)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if withFeature {
|
||||
for _, fv := range layer.Features {
|
||||
f, e := pb.FeatureFromDatabaseModel(fv, withVulnerability)
|
||||
if e != nil {
|
||||
err = e
|
||||
return
|
||||
}
|
||||
|
||||
features = append(features, f)
|
||||
}
|
||||
}
|
||||
|
||||
ancestry.Name = name
|
||||
ancestry.EngineVersion = int32(layer.EngineVersion)
|
||||
for name != "" {
|
||||
layer, err = s.Store.FindLayer(name, false, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if layer.Parent != nil {
|
||||
name = layer.Parent.Name
|
||||
} else {
|
||||
name = ""
|
||||
}
|
||||
|
||||
layers = append(layers, pb.LayerFromDatabaseModel(layer))
|
||||
}
|
||||
|
||||
// reverse layers to make the root layer at the top
|
||||
for i, j := 0, len(layers)-1; i < j; i, j = i+1, j-1 {
|
||||
layers[i], layers[j] = layers[j], layers[i]
|
||||
}
|
||||
|
||||
ancestry.Layers = layers
|
||||
return
|
||||
}
|
223
api/v2/server.go
Normal file
223
api/v2/server.go
Normal file
@ -0,0 +1,223 @@
|
||||
// Copyright 2017 clair authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cockroachdb/cmux"
|
||||
"github.com/grpc-ecosystem/go-grpc-prometheus"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
|
||||
pb "github.com/coreos/clair/api/v2/clairpb"
|
||||
"github.com/coreos/clair/database"
|
||||
)
|
||||
|
||||
// handleShutdown handles the server shut down error.
|
||||
func handleShutdown(err error) {
|
||||
if err != nil {
|
||||
if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
promResponseDurationMilliseconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Name: "clair_v2_api_response_duration_milliseconds",
|
||||
Help: "The duration of time it takes to receieve and write a response to an V2 API request",
|
||||
Buckets: prometheus.ExponentialBuckets(9.375, 2, 10),
|
||||
}, []string{"route", "code"})
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(promResponseDurationMilliseconds)
|
||||
}
|
||||
|
||||
func newGrpcServer(paginationKey string, store database.Datastore, tlsConfig *tls.Config) *grpc.Server {
|
||||
grpcOpts := []grpc.ServerOption{
|
||||
grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
|
||||
grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
|
||||
}
|
||||
|
||||
if tlsConfig != nil {
|
||||
grpcOpts = append(grpcOpts, grpc.Creds(credentials.NewTLS(tlsConfig)))
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer(grpcOpts...)
|
||||
pb.RegisterAncestryServiceServer(grpcServer, &AncestryServer{Store: store})
|
||||
pb.RegisterNotificationServiceServer(grpcServer, &NotificationServer{PaginationKey: paginationKey, Store: store})
|
||||
return grpcServer
|
||||
}
|
||||
|
||||
type httpStatusWritter struct {
|
||||
http.ResponseWriter
|
||||
|
||||
StatusCode int
|
||||
}
|
||||
|
||||
func (w *httpStatusWritter) WriteHeader(code int) {
|
||||
w.StatusCode = code
|
||||
w.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
// logHandler adds request logging to an http handler.
|
||||
func logHandler(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
lrw := &httpStatusWritter{ResponseWriter: w, StatusCode: http.StatusOK}
|
||||
|
||||
handler.ServeHTTP(lrw, r)
|
||||
|
||||
statusStr := strconv.Itoa(lrw.StatusCode)
|
||||
if lrw.StatusCode == 0 {
|
||||
statusStr = "???"
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"remote addr": r.RemoteAddr,
|
||||
"method": r.Method,
|
||||
"request uri": r.RequestURI,
|
||||
"status": statusStr,
|
||||
"elapsed time": time.Since(start),
|
||||
}).Info("Handled HTTP request")
|
||||
})
|
||||
}
|
||||
|
||||
func newGrpcGatewayServer(ctx context.Context, listenerAddr string, tlsConfig *tls.Config) http.Handler {
|
||||
var (
|
||||
gwTLSConfig *tls.Config
|
||||
gwOpts []grpc.DialOption
|
||||
)
|
||||
|
||||
if tlsConfig != nil {
|
||||
gwTLSConfig = tlsConfig.Clone()
|
||||
gwTLSConfig.InsecureSkipVerify = true
|
||||
gwOpts = append(gwOpts, grpc.WithTransportCredentials(credentials.NewTLS(gwTLSConfig)))
|
||||
} else {
|
||||
gwOpts = append(gwOpts, grpc.WithInsecure())
|
||||
}
|
||||
|
||||
// changes json serializer to include empty fields with default values
|
||||
jsonOpt := runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{EmitDefaults: true})
|
||||
gwmux := runtime.NewServeMux(jsonOpt)
|
||||
|
||||
conn, err := grpc.DialContext(ctx, listenerAddr, gwOpts...)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("could not initialize grpc gateway connection")
|
||||
}
|
||||
|
||||
err = pb.RegisterAncestryServiceHandler(ctx, gwmux, conn)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("could not initialize ancestry grpc gateway")
|
||||
}
|
||||
|
||||
err = pb.RegisterNotificationServiceHandler(ctx, gwmux, conn)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("could not initialize notification grpc gateway")
|
||||
}
|
||||
|
||||
return logHandler(gwmux)
|
||||
}
|
||||
|
||||
func servePrometheus(mux *http.ServeMux) {
|
||||
mux.Handle("/metrics", prometheus.Handler())
|
||||
}
|
||||
|
||||
// Run initializes grpc and grpc gateway api services on the same port
|
||||
func Run(GrpcPort int, tlsConfig *tls.Config, PaginationKey, CertFile, KeyFile string, store database.Datastore) {
|
||||
l, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", GrpcPort))
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("could not bind to port %d", GrpcPort)
|
||||
}
|
||||
log.WithField("addr", l.Addr().String()).Info("starting grpc server")
|
||||
|
||||
var (
|
||||
apiHandler http.Handler
|
||||
apiListener net.Listener
|
||||
srv *http.Server
|
||||
ctx = context.Background()
|
||||
httpMux = http.NewServeMux()
|
||||
tcpMux = cmux.New(l)
|
||||
)
|
||||
|
||||
if tlsConfig != nil {
|
||||
cert, err := tls.LoadX509KeyPair(CertFile, KeyFile)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("Failed to load certificate files")
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||
tlsConfig.NextProtos = []string{"h2"}
|
||||
|
||||
apiListener = tls.NewListener(tcpMux.Match(cmux.Any()), tlsConfig)
|
||||
go func() { handleShutdown(tcpMux.Serve()) }()
|
||||
|
||||
grpcServer := newGrpcServer(PaginationKey, store, tlsConfig)
|
||||
gwmux := newGrpcGatewayServer(ctx, apiListener.Addr().String(), tlsConfig)
|
||||
|
||||
httpMux.Handle("/", gwmux)
|
||||
servePrometheus(httpMux)
|
||||
apiHandler = grpcHandlerFunc(grpcServer, httpMux)
|
||||
|
||||
log.Info("grpc server is configured with client certificate authentication")
|
||||
} else {
|
||||
grpcL := tcpMux.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))
|
||||
apiListener = tcpMux.Match(cmux.Any())
|
||||
go func() { handleShutdown(tcpMux.Serve()) }()
|
||||
|
||||
grpcServer := newGrpcServer(PaginationKey, store, nil)
|
||||
go func() { handleShutdown(grpcServer.Serve(grpcL)) }()
|
||||
|
||||
gwmux := newGrpcGatewayServer(ctx, apiListener.Addr().String(), nil)
|
||||
|
||||
httpMux.Handle("/", gwmux)
|
||||
servePrometheus(httpMux)
|
||||
apiHandler = httpMux
|
||||
|
||||
log.Warn("grpc server is configured without client certificate authentication")
|
||||
}
|
||||
|
||||
srv = &http.Server{
|
||||
Handler: apiHandler,
|
||||
TLSConfig: tlsConfig,
|
||||
}
|
||||
|
||||
// blocking call
|
||||
handleShutdown(srv.Serve(apiListener))
|
||||
log.Info("Grpc API stopped")
|
||||
}
|
||||
|
||||
// grpcHandlerFunc returns an http.Handler that delegates to grpcServer on incoming gRPC
|
||||
// connections or otherHandler otherwise. Copied from cockroachdb.
|
||||
func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
|
||||
grpcServer.ServeHTTP(w, r)
|
||||
} else {
|
||||
otherHandler.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
}
|
@ -59,6 +59,7 @@ func DefaultConfig() Config {
|
||||
API: &api.Config{
|
||||
Port: 6060,
|
||||
HealthPort: 6061,
|
||||
GrpcPort: 6070,
|
||||
Timeout: 900 * time.Second,
|
||||
},
|
||||
Notifier: ¬ification.Config{
|
||||
|
@ -104,6 +104,7 @@ func Boot(config *Config) {
|
||||
// Start API
|
||||
st.Begin()
|
||||
go api.Run(config.API, db, st)
|
||||
go api.RunV2(config.API, db)
|
||||
st.Begin()
|
||||
go api.RunHealth(config.API, db, st)
|
||||
|
||||
|
@ -29,7 +29,7 @@ clair:
|
||||
api:
|
||||
# API server port
|
||||
port: 6060
|
||||
|
||||
grpcPort: 6070
|
||||
# Health server port
|
||||
# This is an unencrypted endpoint useful for load balancers to check to healthiness of the clair server.
|
||||
healthport: 6061
|
||||
|
65
glide.lock
generated
65
glide.lock
generated
@ -1,10 +1,12 @@
|
||||
hash: 74b5b23a00a6db4941521bf3adc5ca49a1ab15c857534177654bacc9fc74cdfe
|
||||
updated: 2017-05-05T11:40:41.533307281-04:00
|
||||
hash: b5b9ebebad30becd361736196a015af23b1d9a616a375c7fc13823121fd17226
|
||||
updated: 2017-06-05T16:11:29.019891941-04:00
|
||||
imports:
|
||||
- name: github.com/beorn7/perks
|
||||
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||
subpackages:
|
||||
- quantile
|
||||
- name: github.com/cockroachdb/cmux
|
||||
version: 30d10be492927e2dcae0089c374c455d42414fcb
|
||||
- name: github.com/coreos/pkg
|
||||
version: 3ac0863d7acf3bc44daf49afef8919af12f704ef
|
||||
subpackages:
|
||||
@ -16,9 +18,22 @@ imports:
|
||||
- name: github.com/fernet/fernet-go
|
||||
version: 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2
|
||||
- name: github.com/golang/protobuf
|
||||
version: 18c9bb3261723cd5401db4d0c9fbc5c3b6c70fe8
|
||||
version: 5a0f697c9ed9d68fef0116532c6e05cfeae00e55
|
||||
subpackages:
|
||||
- jsonpb
|
||||
- proto
|
||||
- protoc-gen-go/descriptor
|
||||
- ptypes/any
|
||||
- ptypes/empty
|
||||
- ptypes/struct
|
||||
- name: github.com/grpc-ecosystem/go-grpc-prometheus
|
||||
version: 2500245aa6110c562d17020fb31a2c133d737799
|
||||
- name: github.com/grpc-ecosystem/grpc-gateway
|
||||
version: 2a40dd79571b760642c30f62ada35c65ac2b779c
|
||||
subpackages:
|
||||
- runtime
|
||||
- runtime/internal
|
||||
- utilities
|
||||
- name: github.com/guregu/null
|
||||
version: 41961cea0328defc5f95c1c473f89ebf0d1813f6
|
||||
subpackages:
|
||||
@ -30,7 +45,7 @@ imports:
|
||||
- name: github.com/julienschmidt/httprouter
|
||||
version: 8c199fb6259ffc1af525cc3ad52ee60ba8359669
|
||||
- name: github.com/lib/pq
|
||||
version: 2704adc878c21e1329f46f6e56a1c387d788ff94
|
||||
version: 8837942c3e09574accbc5f150e2c5e057189cace
|
||||
subpackages:
|
||||
- oid
|
||||
- name: github.com/matttproud/golang_protobuf_extensions
|
||||
@ -58,7 +73,7 @@ imports:
|
||||
- internal/bitbucket.org/ww/goautoneg
|
||||
- model
|
||||
- name: github.com/prometheus/procfs
|
||||
version: d098ca18df8bc825079013daf7bacefbb1ee877e
|
||||
version: 65c1f6f8f0fc1e2185eb9863a3bc751496404259
|
||||
subpackages:
|
||||
- xfs
|
||||
- name: github.com/remind101/migrate
|
||||
@ -71,10 +86,48 @@ imports:
|
||||
- assert
|
||||
- name: github.com/tylerb/graceful
|
||||
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
|
||||
- name: golang.org/x/net
|
||||
version: 59a0b19b5533c7977ddeb86b017bf507ed407b12
|
||||
subpackages:
|
||||
- context
|
||||
- http2
|
||||
- http2/hpack
|
||||
- idna
|
||||
- internal/timeseries
|
||||
- lex/httplex
|
||||
- trace
|
||||
- name: golang.org/x/sys
|
||||
version: 9ccfe848b9db8435a24c424abbc07a921adf1df5
|
||||
version: b90f89a1e7a9c1f6b918820b3daa7f08488c8594
|
||||
subpackages:
|
||||
- unix
|
||||
- name: golang.org/x/text
|
||||
version: ccbd3f7822129ff389f8ca4858a9b9d4d910531c
|
||||
subpackages:
|
||||
- secure/bidirule
|
||||
- transform
|
||||
- unicode/bidi
|
||||
- unicode/norm
|
||||
- name: google.golang.org/genproto
|
||||
version: aa2eb687b4d3e17154372564ad8d6bf11c3cf21f
|
||||
subpackages:
|
||||
- googleapis/api/annotations
|
||||
- googleapis/rpc/status
|
||||
- name: google.golang.org/grpc
|
||||
version: 8de2dff78c3b968a51c99ec526d934f686537437
|
||||
subpackages:
|
||||
- codes
|
||||
- credentials
|
||||
- grpclb/grpc_lb_v1
|
||||
- grpclog
|
||||
- internal
|
||||
- keepalive
|
||||
- metadata
|
||||
- naming
|
||||
- peer
|
||||
- stats
|
||||
- status
|
||||
- tap
|
||||
- transport
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b
|
||||
testImports: []
|
||||
|
@ -29,3 +29,4 @@ import:
|
||||
- package: github.com/tylerb/graceful
|
||||
version: ^1.2.15
|
||||
- package: gopkg.in/yaml.v2
|
||||
- package: github.com/cockroachdb/cmux
|
||||
|
Loading…
Reference in New Issue
Block a user