From dc99d45f47392f833ad254cbccfb190b5fc5acdc Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Mon, 1 Feb 2016 15:42:57 -0500 Subject: [PATCH] api: refactor endpoints and implement get vulnerability --- api/v1/models.go | 103 +++++++++++++++++++++++++++++++++++++++++++++++ api/v1/routes.go | 88 +++++++++------------------------------- 2 files changed, 122 insertions(+), 69 deletions(-) diff --git a/api/v1/models.go b/api/v1/models.go index 1958ff60..00d1c881 100644 --- a/api/v1/models.go +++ b/api/v1/models.go @@ -14,6 +14,13 @@ package v1 +import ( + "errors" + + "github.com/coreos/clair/database" + "github.com/coreos/clair/utils/types" +) + type Error struct { Message string `json:"Layer` } @@ -28,6 +35,48 @@ type Layer struct { Features []Feature `json:"Features,omitempty"` } +func LayerFromDatabaseModel(dbLayer database.Layer, withFeatures, withVulnerabilities bool) Layer { + layer := Layer{ + Name: dbLayer.Name, + IndexedByVersion: dbLayer.EngineVersion, + } + + if dbLayer.Parent != nil { + layer.ParentName = dbLayer.Parent.Name + } + + if dbLayer.Namespace != nil { + layer.Namespace = dbLayer.Namespace.Name + } + + if withFeatures || withVulnerabilities && dbLayer.Features != nil { + for _, dbFeatureVersion := range dbLayer.Features { + feature := Feature{ + Name: dbFeatureVersion.Feature.Name, + Namespace: dbFeatureVersion.Feature.Namespace.Name, + Version: dbFeatureVersion.Version.String(), + } + + for _, dbVuln := range dbFeatureVersion.AffectedBy { + vuln := Vulnerability{ + Name: dbVuln.Name, + Namespace: dbVuln.Namespace.Name, + Description: dbVuln.Description, + Severity: string(dbVuln.Severity), + } + + if dbVuln.FixedBy != types.MaxVersion { + vuln.FixedBy = dbVuln.FixedBy.String() + } + feature.Vulnerabilities = append(feature.Vulnerabilities, vuln) + } + layer.Features = append(layer.Features, feature) + } + } + + return layer +} + type Vulnerability struct { Name string `json:"Name,omitempty"` Namespace string `json:"Namespace,omitempty"` @@ -38,6 +87,60 @@ type Vulnerability struct { FixedIn []Feature `json:"FixedIn,omitempty"` } +func (v Vulnerability) DatabaseModel() (database.Vulnerability, error) { + severity := types.Priority(v.Severity) + if !severity.IsValid() { + return database.Vulnerability{}, errors.New("Invalid severity") + } + + var dbFeatures []database.FeatureVersion + for _, feature := range v.FixedIn { + version, err := types.NewVersion(feature.Version) + if err != nil { + return database.Vulnerability{}, err + } + + dbFeatures = append(dbFeatures, database.FeatureVersion{ + Feature: database.Feature{ + Name: feature.Name, + Namespace: database.Namespace{Name: feature.Namespace}, + }, + Version: version, + }) + } + + return database.Vulnerability{ + Name: v.Name, + Namespace: database.Namespace{Name: v.Namespace}, + Description: v.Description, + Link: v.Link, + Severity: severity, + FixedIn: dbFeatures, + }, nil +} + +func VulnerabilityFromDatabaseModel(dbVuln database.Vulnerability, withFixedIn bool) Vulnerability { + vuln := Vulnerability{ + Name: dbVuln.Name, + Namespace: dbVuln.Namespace.Name, + Description: dbVuln.Description, + Link: dbVuln.Link, + Severity: string(dbVuln.Severity), + } + + if withFixedIn { + for _, dbFeatureVersion := range dbVuln.FixedIn { + vuln.FixedIn = append(vuln.FixedIn, Feature{ + Name: dbFeatureVersion.Feature.Name, + Namespace: dbFeatureVersion.Feature.Namespace.Name, + Version: dbFeatureVersion.Version.String(), + }) + } + } + + return vuln +} + type Feature struct { Name string `json:"Name,omitempty"` Namespace string `json:"Namespace,omitempty"` diff --git a/api/v1/routes.go b/api/v1/routes.go index 57b18962..ab9137ee 100644 --- a/api/v1/routes.go +++ b/api/v1/routes.go @@ -25,7 +25,6 @@ import ( "github.com/coreos/clair/api/context" "github.com/coreos/clair/database" cerrors "github.com/coreos/clair/utils/errors" - "github.com/coreos/clair/utils/types" "github.com/coreos/clair/worker" ) @@ -88,43 +87,7 @@ func getLayer(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx * return writeHeader(w, http.StatusInternalServerError) } - layer := Layer{ - Name: dbLayer.Name, - IndexedByVersion: dbLayer.EngineVersion, - } - - if dbLayer.Parent != nil { - layer.ParentName = dbLayer.Parent.Name - } - - if dbLayer.Namespace != nil { - layer.Namespace = dbLayer.Namespace.Name - } - - if withFeatures || withVulnerabilities && dbLayer.Features != nil { - for _, dbFeatureVersion := range dbLayer.Features { - feature := Feature{ - Name: dbFeatureVersion.Feature.Name, - Namespace: dbFeatureVersion.Feature.Namespace.Name, - Version: dbFeatureVersion.Version.String(), - } - - for _, dbVuln := range dbFeatureVersion.AffectedBy { - vuln := Vulnerability{ - Name: dbVuln.Name, - Namespace: dbVuln.Namespace.Name, - Description: dbVuln.Description, - Severity: string(dbVuln.Severity), - } - - if dbVuln.FixedBy != types.MaxVersion { - vuln.FixedBy = dbVuln.FixedBy.String() - } - feature.Vulnerabilities = append(feature.Vulnerabilities, vuln) - } - layer.Features = append(layer.Features, feature) - } - } + layer := LayerFromDatabaseModel(dbLayer, withFeatures, withVulnerabilities) writeResponse(w, LayerEnvelope{Layer: &layer}) return writeHeader(w, http.StatusOK) @@ -171,38 +134,12 @@ func postVulnerability(w http.ResponseWriter, r *http.Request, p httprouter.Para return writeHeader(w, http.StatusBadRequest) } - severity := types.Priority(request.Vulnerability.Severity) - if !severity.IsValid() { - writeResponse(w, VulnerabilityEnvelope{Error: &Error{"invalid severity"}}) + vuln, err := request.Vulnerability.DatabaseModel() + if err != nil { + writeResponse(w, VulnerabilityEnvelope{Error: &Error{err.Error()}}) return writeHeader(w, http.StatusBadRequest) } - var dbFeatures []database.FeatureVersion - for _, feature := range request.Vulnerability.FixedIn { - version, err := types.NewVersion(feature.Version) - if err != nil { - writeResponse(w, VulnerabilityEnvelope{Error: &Error{err.Error()}}) - return writeHeader(w, http.StatusBadRequest) - } - - dbFeatures = append(dbFeatures, database.FeatureVersion{ - Feature: database.Feature{ - Name: feature.Name, - Namespace: database.Namespace{Name: feature.Namespace}, - }, - Version: version, - }) - } - - vuln := database.Vulnerability{ - Name: request.Vulnerability.Name, - Namespace: database.Namespace{Name: request.Vulnerability.Namespace}, - Description: request.Vulnerability.Description, - Link: request.Vulnerability.Link, - Severity: severity, - FixedIn: dbFeatures, - } - err = ctx.Store.InsertVulnerabilities([]database.Vulnerability{vuln}) if err != nil { writeResponse(w, VulnerabilityEnvelope{Error: &Error{err.Error()}}) @@ -213,8 +150,21 @@ func postVulnerability(w http.ResponseWriter, r *http.Request, p httprouter.Para } func getVulnerability(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *context.RouteContext) int { - // ez - return 0 + _, withFixedIn := r.URL.Query()["fixedIn"] + + dbVuln, err := ctx.Store.FindVulnerability(p.ByName("namespaceName"), p.ByName("vulnerabilityName")) + if err == cerrors.ErrNotFound { + writeResponse(w, VulnerabilityEnvelope{Error: &Error{err.Error()}}) + return writeHeader(w, http.StatusNotFound) + } else if err != nil { + writeResponse(w, VulnerabilityEnvelope{Error: &Error{err.Error()}}) + return writeHeader(w, http.StatusInternalServerError) + } + + vuln := VulnerabilityFromDatabaseModel(dbVuln, withFixedIn) + + writeResponse(w, VulnerabilityEnvelope{Vulnerability: &vuln}) + return writeHeader(w, http.StatusOK) } func patchVulnerability(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx *context.RouteContext) int { // ez