github.com/quay/claircore@v1.5.28/rhel/rhcc/scanner_test.go (about)

     1  package rhcc
     2  
     3  import (
     4  	"archive/tar"
     5  	"context"
     6  	"encoding/json"
     7  	"io"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"os"
    11  	"path"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/google/go-cmp/cmp"
    16  	"github.com/quay/zlog"
    17  
    18  	"github.com/quay/claircore"
    19  	"github.com/quay/claircore/test"
    20  )
    21  
    22  func TestContainerScanner(t *testing.T) {
    23  	t.Parallel()
    24  	ctx := zlog.Test(context.Background(), t)
    25  	clairSourceContainer := &claircore.Package{
    26  		Name:    "quay-clair-container",
    27  		Version: "v3.5.5-4",
    28  		NormalizedVersion: claircore.Version{
    29  			Kind: "rhctag",
    30  			V:    [10]int32{3, 5},
    31  		},
    32  		Kind:           claircore.SOURCE,
    33  		PackageDB:      "root/buildinfo/Dockerfile-quay-clair-rhel8-v3.5.5-4",
    34  		RepositoryHint: "rhcc",
    35  		Arch:           "x86_64",
    36  	}
    37  
    38  	quaySourceContainer := &claircore.Package{
    39  		Name:    "quay-registry-container",
    40  		Version: "v3.5.6-4",
    41  		NormalizedVersion: claircore.Version{
    42  			Kind: "rhctag",
    43  			V:    [10]int32{3, 5},
    44  		},
    45  		Kind:           claircore.SOURCE,
    46  		PackageDB:      "root/buildinfo/Dockerfile-quay-quay-rhel8-v3.5.6-4",
    47  		RepositoryHint: "rhcc",
    48  		Arch:           "x86_64",
    49  	}
    50  
    51  	loggingSourceContainer := &claircore.Package{
    52  		Name:    "logging-elasticsearch6-container",
    53  		Version: "v4.6.0-202112132021.p0.g2a13a81.assembly.stream",
    54  		NormalizedVersion: claircore.Version{
    55  			Kind: "rhctag",
    56  			V:    [10]int32{4, 6},
    57  		},
    58  		Kind:           claircore.SOURCE,
    59  		PackageDB:      "root/buildinfo/Dockerfile-openshift-ose-logging-elasticsearch6-v4.6.0-202112132021.p0.g2a13a81.assembly.stream",
    60  		RepositoryHint: "rhcc",
    61  		Arch:           "x86_64",
    62  	}
    63  	name2reposData := map[string]map[string][]string{
    64  		"data": {"openshift/ose-logging-elasticsearch6": {"openshift4/ose-logging-elasticsearch6"}},
    65  	}
    66  
    67  	type testcase struct {
    68  		Name       string
    69  		Dockerfile string
    70  		Want       []*claircore.Package
    71  	}
    72  	table := []testcase{
    73  		{
    74  			Name:       "Quay",
    75  			Dockerfile: "testdata/Dockerfile-quay-quay-rhel8-v3.5.6-4",
    76  			Want: []*claircore.Package{
    77  				quaySourceContainer,
    78  				{
    79  					Name:    "quay/quay-rhel8",
    80  					Version: "v3.5.6-4",
    81  					NormalizedVersion: claircore.Version{
    82  						Kind: "rhctag",
    83  						V:    [10]int32{3, 5},
    84  					},
    85  					Kind:           claircore.BINARY,
    86  					Source:         quaySourceContainer,
    87  					PackageDB:      "root/buildinfo/Dockerfile-quay-quay-rhel8-v3.5.6-4",
    88  					RepositoryHint: "rhcc",
    89  					Arch:           "x86_64",
    90  				},
    91  			},
    92  		},
    93  		{
    94  			Name:       "Clair",
    95  			Dockerfile: "testdata/Dockerfile-quay-clair-rhel8-v3.5.5-4",
    96  			Want: []*claircore.Package{
    97  				clairSourceContainer,
    98  				{
    99  					Name:    "quay/clair-rhel8",
   100  					Version: "v3.5.5-4",
   101  					NormalizedVersion: claircore.Version{
   102  						Kind: "rhctag",
   103  						V:    [10]int32{3, 5},
   104  					},
   105  					Kind:           claircore.BINARY,
   106  					Source:         clairSourceContainer,
   107  					PackageDB:      "root/buildinfo/Dockerfile-quay-clair-rhel8-v3.5.5-4",
   108  					RepositoryHint: "rhcc",
   109  					Arch:           "x86_64",
   110  				},
   111  			},
   112  		},
   113  		{
   114  			Name:       "Elasticsearch",
   115  			Dockerfile: "testdata/Dockerfile-openshift-ose-logging-elasticsearch6-v4.6.0-202112132021.p0.g2a13a81.assembly.stream",
   116  			Want: []*claircore.Package{
   117  				loggingSourceContainer,
   118  				{
   119  					Name:    "openshift4/ose-logging-elasticsearch6",
   120  					Version: "v4.6.0-202112132021.p0.g2a13a81.assembly.stream",
   121  					NormalizedVersion: claircore.Version{
   122  						Kind: "rhctag",
   123  						V:    [10]int32{4, 6},
   124  					},
   125  					Kind:           claircore.BINARY,
   126  					Source:         loggingSourceContainer,
   127  					PackageDB:      "root/buildinfo/Dockerfile-openshift-ose-logging-elasticsearch6-v4.6.0-202112132021.p0.g2a13a81.assembly.stream",
   128  					RepositoryHint: "rhcc",
   129  					Arch:           "x86_64",
   130  				},
   131  			},
   132  		},
   133  	}
   134  	mux := http.NewServeMux()
   135  	mux.HandleFunc("/container-name-repos-map.json", func(w http.ResponseWriter, _ *http.Request) {
   136  		w.Header().Set("last-modified", "Mon, 02 Jan 2006 15:04:05 MST")
   137  		if err := json.NewEncoder(w).Encode(name2reposData); err != nil {
   138  			t.Fatal(err)
   139  		}
   140  	})
   141  	srv := httptest.NewServer(mux)
   142  	defer srv.Close()
   143  	var cs scanner
   144  	cf := func(v interface{}) error {
   145  		cfg := v.(*ScannerConfig)
   146  		cfg.Name2ReposMappingURL = srv.URL + "/container-name-repos-map.json"
   147  		return nil
   148  	}
   149  	if err := cs.Configure(ctx, cf, srv.Client()); err != nil {
   150  		t.Error(err)
   151  	}
   152  
   153  	a := test.NewCachedArena(t)
   154  	t.Cleanup(func() {
   155  		if err := a.Close(ctx); err != nil {
   156  			t.Error(err)
   157  		}
   158  	})
   159  	for _, tt := range table {
   160  		t.Run(tt.Name, func(t *testing.T) {
   161  			ctx := zlog.Test(ctx, t)
   162  			mod := test.Modtime(t, tt.Dockerfile)
   163  			a.GenerateLayer(t, tt.Name, mod, func(t testing.TB, w *os.File) {
   164  				dockerfile, err := os.Open(tt.Dockerfile)
   165  				if err != nil {
   166  					t.Fatal(err)
   167  				}
   168  				defer dockerfile.Close()
   169  				fi, err := dockerfile.Stat()
   170  				if err != nil {
   171  					t.Fatal(err)
   172  				}
   173  				tw := tar.NewWriter(w)
   174  				hdr, err := tar.FileInfoHeader(fi, "")
   175  				if err != nil {
   176  					t.Fatal(err)
   177  				}
   178  				hdr.Name = path.Join("root/buildinfo", path.Base(tt.Dockerfile))
   179  				if err := tw.WriteHeader(hdr); err != nil {
   180  					t.Error(err)
   181  				}
   182  				if _, err := io.Copy(tw, dockerfile); err != nil {
   183  					t.Error(err)
   184  				}
   185  				if err := tw.Close(); err != nil {
   186  					t.Error(err)
   187  				}
   188  				t.Logf("wrote tar to: %s", w.Name())
   189  			})
   190  
   191  			r := a.Realizer(ctx).(*test.CachedRealizer)
   192  			defer func() {
   193  				if err := r.Close(); err != nil {
   194  					t.Error(err)
   195  				}
   196  			}()
   197  			ls, err := r.RealizeDescriptions(ctx, []claircore.LayerDescription{{
   198  				Digest:    "sha256:" + strings.Repeat("beef", 16),
   199  				URI:       "file:" + tt.Name,
   200  				MediaType: test.MediaType,
   201  				Headers:   make(map[string][]string),
   202  			}})
   203  			if err != nil {
   204  				t.Error(err)
   205  			}
   206  
   207  			got, err := cs.Scan(ctx, &ls[0])
   208  			if err != nil {
   209  				t.Error(err)
   210  			}
   211  			t.Logf("found %d packages", len(got))
   212  			if !cmp.Equal(got, tt.Want) {
   213  				t.Error(cmp.Diff(got, tt.Want))
   214  			}
   215  		})
   216  	}
   217  }