Api: add NamespaceName attribute to post Layer

Allow user to specify NamespaceName if not found by featurens
pull/424/head
Grégoire Unbekandt 7 years ago
parent 5856c9fcb6
commit 45bf0ef86a

@ -109,7 +109,7 @@ func postLayer(w http.ResponseWriter, r *http.Request, p httprouter.Params, ctx
return postLayerRoute, http.StatusBadRequest
}
err = clair.ProcessLayer(ctx.Store, request.Layer.Format, request.Layer.Name, request.Layer.ParentName, request.Layer.Path, request.Layer.Headers)
err = clair.ProcessLayer(ctx.Store, request.Layer.Format, request.Layer.Name, request.Layer.ParentName, request.Layer.Path, request.Layer.Headers, request.Layer.NamespaceName)
if err != nil {
if err == tarutil.ErrCouldNotExtract ||
err == tarutil.ErrExtractedFileTooBig ||

@ -56,7 +56,7 @@ func cleanURL(str string) string {
//
// TODO(Quentin-M): We could have a goroutine that looks for layers that have
// been analyzed with an older engine version and that processes them.
func ProcessLayer(datastore database.Datastore, imageFormat, name, parentName, path string, headers map[string]string) error {
func ProcessLayer(datastore database.Datastore, imageFormat, name, parentName, path string, headers map[string]string, namespaceName string) error {
// Verify parameters.
if name == "" {
return commonerr.NewBadRequestError("could not process a layer which does not have a name")
@ -104,8 +104,19 @@ func ProcessLayer(datastore database.Datastore, imageFormat, name, parentName, p
log.WithFields(log.Fields{logLayerName: name, "past engine version": layer.EngineVersion, "current engine version": Version}).Debug("layer content has already been processed in the past with older engine. analyzing again")
}
// Check to see if the user's provided Namespace exists
var namespace *database.Namespace
if namespaceName != "" {
namespace, err = datastore.GetNamespace(namespaceName)
if err != nil {
if err == commonerr.ErrNotFound {
return commonerr.NewBadRequestError("could not find provided namespace")
}
return err
}
}
// Analyze the content.
layer.Namespace, layer.Features, err = detectContent(imageFormat, name, path, headers, layer.Parent)
layer.Namespace, layer.Features, err = detectContent(imageFormat, name, path, headers, layer.Parent, namespace)
if err != nil {
return err
}
@ -115,7 +126,7 @@ func ProcessLayer(datastore database.Datastore, imageFormat, name, parentName, p
// detectContent downloads a layer's archive and extracts its Namespace and
// Features.
func detectContent(imageFormat, name, path string, headers map[string]string, parent *database.Layer) (namespace *database.Namespace, featureVersions []database.FeatureVersion, err error) {
func detectContent(imageFormat, name, path string, headers map[string]string, parent *database.Layer, ns *database.Namespace) (namespace *database.Namespace, featureVersions []database.FeatureVersion, err error) {
totalRequiredFiles := append(featurefmt.RequiredFilenames(), featurens.RequiredFilenames()...)
files, err := imagefmt.Extract(imageFormat, path, headers, totalRequiredFiles)
if err != nil {
@ -128,6 +139,11 @@ func detectContent(imageFormat, name, path string, headers map[string]string, pa
return
}
if namespace == nil && ns != nil {
log.WithFields(log.Fields{logLayerName: name, "namespace provided by user": ns.Name}).Debug("detected namespace")
namespace = ns
}
// Detect features.
featureVersions, err = detectFeatureVersions(name, files, namespace, parent)
if err != nil {

@ -34,12 +34,14 @@ import (
type mockDatastore struct {
database.MockDatastore
layers map[string]database.Layer
layers map[string]database.Layer
namespaces map[string]database.Namespace
}
func newMockDatastore() *mockDatastore {
return &mockDatastore{
layers: make(map[string]database.Layer),
layers: make(map[string]database.Layer),
namespaces: make(map[string]database.Namespace),
}
}
@ -59,6 +61,15 @@ func TestProcessWithDistUpgrade(t *testing.T) {
}
return database.Layer{}, commonerr.ErrNotFound
}
datastore.FctGetNamespace = func(namespaceName string) (*database.Namespace, error) {
if namespace, exists := datastore.namespaces[namespaceName]; exists {
return &namespace, nil
}
return nil, commonerr.ErrNotFound
}
// Add Namespace
datastore.namespaces["debian:7"] = database.Namespace{Name: "debian:7"}
// Create the list of FeatureVersions that should not been upgraded from one layer to another.
nonUpgradedFeatureVersions := []database.FeatureVersion{
@ -78,9 +89,17 @@ func TestProcessWithDistUpgrade(t *testing.T) {
// wheezy.tar: FROM debian:wheezy
// jessie.tar: RUN sed -i "s/precise/trusty/" /etc/apt/sources.list && apt-get update &&
// apt-get -y dist-upgrade
assert.Nil(t, ProcessLayer(datastore, "Docker", "blank", "", testDataPath+"blank.tar.gz", nil))
assert.Nil(t, ProcessLayer(datastore, "Docker", "wheezy", "blank", testDataPath+"wheezy.tar.gz", nil))
assert.Nil(t, ProcessLayer(datastore, "Docker", "jessie", "wheezy", testDataPath+"jessie.tar.gz", nil))
assert.Nil(t, ProcessLayer(datastore, "Docker", "blank", "", testDataPath+"blank.tar.gz", nil, ""))
assert.Nil(t, ProcessLayer(datastore, "Docker", "blankWithNamespace", "", testDataPath+"blank.tar.gz", nil, "debian:7"))
assert.Nil(t, ProcessLayer(datastore, "Docker", "wheezy", "blank", testDataPath+"wheezy.tar.gz", nil, ""))
assert.Nil(t, ProcessLayer(datastore, "Docker", "jessie", "wheezy", testDataPath+"jessie.tar.gz", nil, ""))
// Ensure that the 'blankWithNamespace' layer has the provided namespace
blankWithNamespace, ok := datastore.layers["blankWithNamespace"]
if assert.True(t, ok, "layer 'blankWithNamespace' not processed") {
assert.Equal(t, "debian:7", blankWithNamespace.Namespace.Name)
assert.Len(t, blankWithNamespace.Features, 0)
}
// Ensure that the 'wheezy' layer has the expected namespace and features.
wheezy, ok := datastore.layers["wheezy"]

Loading…
Cancel
Save