Skip to content

Commit 454830e

Browse files
committed
all: new exportable indexer and datastore packages (#587)
In order to leverage claircore as a library dependency some packages (and associated interfaces) need to be publicly consumable. This change also unifies the postgres implementations. To implement a new backend or a noop backend it's be good to get all the postgres specific implementation details in one place. Signed-off-by: crozzy <[email protected]>
1 parent 97420ed commit 454830e

File tree

191 files changed

+745
-875
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

191 files changed

+745
-875
lines changed

alpine/distributionscanner.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/quay/zlog"
1414

1515
"github.com/quay/claircore"
16-
"github.com/quay/claircore/internal/indexer"
16+
"github.com/quay/claircore/indexer"
1717
"github.com/quay/claircore/osrelease"
1818
"github.com/quay/claircore/pkg/tarfs"
1919
)

alpine/ecosystem.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package alpine
33
import (
44
"context"
55

6-
"github.com/quay/claircore/internal/indexer"
7-
"github.com/quay/claircore/internal/indexer/linux"
6+
"github.com/quay/claircore/indexer"
7+
"github.com/quay/claircore/indexer/linux"
88
)
99

1010
// NewEcosystem provides the set of scanners and coalescers for the alpine ecosystem

alpine/packagescanner.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/quay/zlog"
1111

1212
"github.com/quay/claircore"
13-
"github.com/quay/claircore/internal/indexer"
13+
"github.com/quay/claircore/indexer"
1414
"github.com/quay/claircore/pkg/tarfs"
1515
)
1616

aws/distributionscanner.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/quay/zlog"
1010

1111
"github.com/quay/claircore"
12-
"github.com/quay/claircore/internal/indexer"
12+
"github.com/quay/claircore/indexer"
1313
)
1414

1515
// AWS Linux keeps a consistent os-release file between

cmd/cctool/unpack.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ func Unpack(cmd context.Context, cfg *commonConfig, args []string) error {
6161
defer done()
6262

6363
log.Printf("fetching layers")
64-
a := &libindex.FetchArena{}
65-
a.Init(http.DefaultClient, os.TempDir())
66-
f := a.Fetcher()
67-
err = f.Fetch(ctx, m.Layers)
64+
a := libindex.NewRemoteFetchArena(http.DefaultClient, os.TempDir())
65+
r := a.Realizer(ctx)
66+
err = r.Realize(ctx, m.Layers)
6867
if err != nil {
6968
return err
7069
}
@@ -115,7 +114,7 @@ func Unpack(cmd context.Context, cfg *commonConfig, args []string) error {
115114
log.Printf("failed to recursively remove %v: %v", td, err)
116115
}
117116
log.Printf("deleting downloaded layers in tmp dir")
118-
err = f.Close()
117+
err = r.Close()
119118
if err != nil {
120119
log.Printf("failed to clean layer files in tmp directory: %v", err)
121120
}

cmd/libindexhttp/main.go

+15-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import (
1111
"github.com/quay/zlog"
1212
"github.com/rs/zerolog"
1313

14+
"github.com/quay/claircore/datastore/postgres"
1415
"github.com/quay/claircore/libindex"
16+
"github.com/quay/claircore/pkg/ctxlock"
1517
)
1618

1719
// Config this struct is using the goconfig library for simple flag and env var
@@ -41,9 +43,19 @@ func main() {
4143
log = log.Level(logLevel(conf))
4244
zlog.Set(&log)
4345

44-
opts := &libindex.Opts{
45-
ConnString: conf.ConnString,
46-
Migrations: true,
46+
pool, err := postgres.Connect(ctx, conf.ConnString, "libindex")
47+
if err != nil {
48+
log.Fatal().Msgf("failed to create db pool: %v", err)
49+
}
50+
store, err := postgres.InitPostgresIndexerStore(ctx, pool, true)
51+
if err != nil {
52+
log.Fatal().Msgf("failed to create store: %v", err)
53+
}
54+
55+
opts := &libindex.Options{
56+
Store: store,
57+
Locker: &ctxlock.Locker{},
58+
FetchArena: libindex.NewRemoteFetchArena(http.DefaultClient, os.TempDir()),
4759
}
4860

4961
// create libindex

internal/vulnstore/enrichment.go datastore/enrichment.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package vulnstore
1+
package datastore
22

33
import (
44
"context"

datastore/matcher_store.go

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package datastore
2+
3+
// MatcherStore aggregates all interface types
4+
type MatcherStore interface {
5+
Updater
6+
Vulnerability
7+
Enrichment
8+
}

internal/indexer/postgres/affected_manifests_e2e_test.go datastore/postgres/affected_manifests_e2e_test.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import (
1212
"github.com/quay/zlog"
1313

1414
"github.com/quay/claircore"
15-
"github.com/quay/claircore/internal/indexer"
15+
"github.com/quay/claircore/indexer"
16+
"github.com/quay/claircore/pkg/omnimatcher"
1617
"github.com/quay/claircore/test/integration"
18+
pgtest "github.com/quay/claircore/test/postgres"
1719
)
1820

1921
type affectedE2E struct {
@@ -27,8 +29,8 @@ type affectedE2E struct {
2729
func TestAffectedE2E(t *testing.T) {
2830
integration.NeedDB(t)
2931
ctx := zlog.Test(context.Background(), t)
30-
pool := TestDatabase(ctx, t)
31-
store := NewStore(pool)
32+
pool := pgtest.TestIndexerDB(ctx, t)
33+
store := NewIndexerStore(pool)
3234

3335
table := []struct {
3436
// name of the defined affectedE2E test
@@ -268,8 +270,9 @@ func (e *affectedE2E) IndexManifest(t *testing.T) {
268270
// manifest is affected.
269271
func (e *affectedE2E) AffectedManifests(t *testing.T) {
270272
ctx := zlog.Test(e.ctx, t)
273+
om := omnimatcher.New(nil)
271274
for _, vuln := range e.vr.Vulnerabilities {
272-
hashes, err := e.store.AffectedManifests(ctx, *vuln)
275+
hashes, err := e.store.AffectedManifests(ctx, *vuln, om.Vulnerable)
273276
if err != nil {
274277
t.Fatalf("failed to retrieve affected manifest for vuln %s: %v", vuln.ID, err)
275278
}

internal/indexer/postgres/affectedmanifest.go datastore/postgres/affectedmanifest.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"github.com/quay/zlog"
1616

1717
"github.com/quay/claircore"
18-
"github.com/quay/claircore/pkg/omnimatcher"
1918
)
2019

2120
var (
@@ -68,7 +67,7 @@ var (
6867
//
6968
// The manifest index is then queried to resolve a list of manifest hashes containing the affected
7069
// artifacts.
71-
func (s *store) AffectedManifests(ctx context.Context, v claircore.Vulnerability) ([]claircore.Digest, error) {
70+
func (s *IndexerStore) AffectedManifests(ctx context.Context, v claircore.Vulnerability, vulnFunc claircore.CheckVulnernableFunc) ([]claircore.Digest, error) {
7271
const (
7372
selectPackages = `
7473
SELECT
@@ -108,7 +107,7 @@ WHERE
108107
);
109108
`
110109
)
111-
ctx = zlog.ContextWithValues(ctx, "component", "internal/indexer/postgres/affectedManifests")
110+
ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/affectedManifests")
112111

113112
// confirm the incoming vuln can be
114113
// resolved into a prototype index record
@@ -179,10 +178,9 @@ WHERE
179178
// for each package discovered create an index record
180179
// and determine if any in-tree matcher finds the record vulnerable
181180
var filteredRecords []claircore.IndexRecord
182-
om := omnimatcher.New(nil)
183181
for _, pkg := range pkgsToFilter {
184182
pr.Package = &pkg
185-
match, err := om.Vulnerable(ctx, &pr, &v)
183+
match, err := vulnFunc(ctx, &pr, &v)
186184
if err != nil {
187185
return nil, err
188186
}
@@ -276,7 +274,7 @@ func protoRecord(ctx context.Context, pool *pgxpool.Pool, v claircore.Vulnerabil
276274
`
277275
timeout = 5 * time.Second
278276
)
279-
ctx = zlog.ContextWithValues(ctx, "component", "internal/indexer/postgres/protoRecord")
277+
ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/protoRecord")
280278

281279
protoRecord := claircore.IndexRecord{}
282280
// fill dist into prototype index record if exists

datastore/postgres/connect.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package postgres
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/jackc/pgx/v4/pgxpool"
8+
"github.com/prometheus/client_golang/prometheus"
9+
"github.com/quay/claircore/pkg/poolstats"
10+
"github.com/quay/zlog"
11+
)
12+
13+
// Connect initialize a postgres pgxpool.Pool based on the connection string
14+
func Connect(ctx context.Context, connString string, applicationName string) (*pgxpool.Pool, error) {
15+
// we are going to use pgx for more control over connection pool and
16+
// and a cleaner api around bulk inserts
17+
cfg, err := pgxpool.ParseConfig(connString)
18+
if err != nil {
19+
return nil, fmt.Errorf("failed to parse ConnString: %v", err)
20+
}
21+
cfg.MaxConns = 30
22+
const appnameKey = `application_name`
23+
params := cfg.ConnConfig.RuntimeParams
24+
if _, ok := params[appnameKey]; !ok {
25+
params[appnameKey] = applicationName
26+
}
27+
28+
pool, err := pgxpool.ConnectConfig(ctx, cfg)
29+
if err != nil {
30+
return nil, fmt.Errorf("failed to create ConnPool: %v", err)
31+
}
32+
33+
if err := prometheus.Register(poolstats.NewCollector(pool, applicationName)); err != nil {
34+
zlog.Info(ctx).Msg("pool metrics already registered")
35+
}
36+
37+
return pool, nil
38+
}

internal/indexer/postgres/deletemanifests.go datastore/postgres/deletemanifests.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ var (
3131
)
3232
)
3333

34-
func (s *store) DeleteManifests(ctx context.Context, d ...claircore.Digest) ([]claircore.Digest, error) {
35-
ctx = zlog.ContextWithValues(ctx, "component", "internal/indexer/postgres/DeleteManifests")
34+
func (s *IndexerStore) DeleteManifests(ctx context.Context, d ...claircore.Digest) ([]claircore.Digest, error) {
35+
ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/DeleteManifests")
3636
rm, err := s.deleteManifests(ctx, d)
3737
if err != nil {
3838
return nil, err
3939
}
4040
return rm, s.layerCleanup(ctx)
4141
}
4242

43-
func (s *store) deleteManifests(ctx context.Context, d []claircore.Digest) ([]claircore.Digest, error) {
43+
func (s *IndexerStore) deleteManifests(ctx context.Context, d []claircore.Digest) ([]claircore.Digest, error) {
4444
const deleteManifest = `DELETE FROM manifest WHERE hash = ANY($1::TEXT[]) RETURNING manifest.hash;`
4545
var err error
4646
defer promTimer(deleteManifestsDuration, "deleteManifest", &err)()
@@ -72,7 +72,7 @@ func (s *store) deleteManifests(ctx context.Context, d []claircore.Digest) ([]cl
7272
return rm, nil
7373
}
7474

75-
func (s *store) layerCleanup(ctx context.Context) (err error) {
75+
func (s *IndexerStore) layerCleanup(ctx context.Context) (err error) {
7676
const layerCleanup = `DELETE FROM layer WHERE NOT EXISTS (SELECT FROM manifest_layer WHERE manifest_layer.layer_id = layer.id);`
7777
defer promTimer(deleteManifestsDuration, "layerCleanup", &err)()
7878
tag, err := s.pool.Exec(ctx, layerCleanup)

internal/indexer/postgres/deletemanifests_test.go datastore/postgres/deletemanifests_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import (
1010
"github.com/quay/claircore"
1111
"github.com/quay/claircore/test"
1212
"github.com/quay/claircore/test/integration"
13+
pgtest "github.com/quay/claircore/test/postgres"
1314
)
1415

1516
func TestDeleteManifests(t *testing.T) {
1617
integration.NeedDB(t)
1718
ctx := zlog.Test(context.Background(), t)
18-
pool := TestDatabase(ctx, t)
19-
store := NewStore(pool)
19+
pool := pgtest.TestIndexerDB(ctx, t)
20+
store := NewIndexerStore(pool)
2021
defer store.Close(ctx)
2122

2223
t.Run("Nonexistent", func(t *testing.T) {
File renamed without changes.
File renamed without changes.

internal/indexer/postgres/distributionsbylayer.go datastore/postgres/distributionsbylayer.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/prometheus/client_golang/prometheus/promauto"
1313

1414
"github.com/quay/claircore"
15-
"github.com/quay/claircore/internal/indexer"
15+
"github.com/quay/claircore/indexer"
1616
)
1717

1818
var (
@@ -37,7 +37,7 @@ var (
3737
)
3838
)
3939

40-
func (s *store) DistributionsByLayer(ctx context.Context, hash claircore.Digest, scnrs indexer.VersionedScanners) ([]*claircore.Distribution, error) {
40+
func (s *IndexerStore) DistributionsByLayer(ctx context.Context, hash claircore.Digest, scnrs indexer.VersionedScanners) ([]*claircore.Distribution, error) {
4141
const (
4242
selectScanner = `
4343
SELECT id
File renamed without changes.

internal/vulnstore/postgres/enrichment.go datastore/postgres/enrichment.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ var (
6363
// UpdateEnrichments creates a new UpdateOperation, inserts the provided
6464
// EnrichmentRecord(s), and ensures enrichments from previous updates are not
6565
// queried by clients.
66-
func (s *Store) UpdateEnrichments(ctx context.Context, name string, fp driver.Fingerprint, es []driver.EnrichmentRecord) (uuid.UUID, error) {
66+
func (s *MatcherStore) UpdateEnrichments(ctx context.Context, name string, fp driver.Fingerprint, es []driver.EnrichmentRecord) (uuid.UUID, error) {
6767
const (
6868
create = `
6969
INSERT
@@ -107,7 +107,7 @@ ON CONFLICT
107107
DO
108108
NOTHING;`
109109
)
110-
ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/UpdateEnrichments")
110+
ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/UpdateEnrichments")
111111

112112
var id uint64
113113
var ref uuid.UUID
@@ -172,7 +172,7 @@ func hashEnrichment(r *driver.EnrichmentRecord) (k string, d []byte) {
172172
return "md5", h.Sum(nil)
173173
}
174174

175-
func (s *Store) GetEnrichment(ctx context.Context, name string, tags []string) (res []driver.EnrichmentRecord, err error) {
175+
func (s *MatcherStore) GetEnrichment(ctx context.Context, name string, tags []string) (res []driver.EnrichmentRecord, err error) {
176176
const query = `
177177
WITH
178178
latest
@@ -195,7 +195,7 @@ WHERE
195195
AND uo.enrich = e.id
196196
AND e.tags && $2::text[];`
197197

198-
ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/GetEnrichment")
198+
ctx = zlog.ContextWithValues(ctx, "component", "datastore/postgres/GetEnrichment")
199199
timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) {
200200
getEnrichmentsDuration.WithLabelValues("query", strconv.FormatBool(errors.Is(err, nil)))
201201
}))

internal/vulnstore/postgres/gc.go datastore/postgres/gc.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const (
5353
// The GC is throttled to not overload the database with cascade deletes.
5454
// If a full GC is required run this method until the returned int64 value
5555
// is 0.
56-
func (s *Store) GC(ctx context.Context, keep int) (int64, error) {
56+
func (s *MatcherStore) GC(ctx context.Context, keep int) (int64, error) {
5757
// obtain update operations which need deletin'
5858
ops, totalOps, err := eligibleUpdateOpts(ctx, s.pool, keep)
5959
if err != nil {

internal/vulnstore/postgres/gc_test.go datastore/postgres/gc_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/quay/claircore/pkg/ctxlock"
1717
"github.com/quay/claircore/test"
1818
"github.com/quay/claircore/test/integration"
19+
pgtest "github.com/quay/claircore/test/postgres"
1920
)
2021

2122
type updaterMock struct {
@@ -102,16 +103,16 @@ func TestGC(t *testing.T) {
102103
for _, tt := range table {
103104
t.Run(tt.name, func(t *testing.T) {
104105
ctx := zlog.Test(context.Background(), t)
105-
pool := TestDB(ctx, t)
106-
store := NewVulnStore(pool)
106+
pool := pgtest.TestMatcherDB(ctx, t)
107+
store := NewMatcherStore(pool)
107108
locks, err := ctxlock.New(ctx, pool)
108109
if err != nil {
109110
t.Error(err)
110111
}
111112
defer locks.Close(ctx)
112113
mgr, err := updates.NewManager(
113114
ctx,
114-
NewVulnStore(pool),
115+
NewMatcherStore(pool),
115116
locks,
116117
http.DefaultClient,
117118
updates.WithEnabled([]string{}),
File renamed without changes.

internal/vulnstore/postgres/get.go datastore/postgres/get.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import (
99
"github.com/jackc/pgx/v4"
1010
"github.com/prometheus/client_golang/prometheus"
1111
"github.com/prometheus/client_golang/prometheus/promauto"
12+
"github.com/quay/claircore/datastore"
1213
"github.com/quay/zlog"
1314

1415
"github.com/quay/claircore"
15-
"github.com/quay/claircore/internal/vulnstore"
1616
)
1717

1818
var (
@@ -37,7 +37,7 @@ var (
3737
)
3838

3939
// Get implements vulnstore.Vulnerability.
40-
func (s *Store) Get(ctx context.Context, records []*claircore.IndexRecord, opts vulnstore.GetOpts) (map[string][]*claircore.Vulnerability, error) {
40+
func (s *MatcherStore) Get(ctx context.Context, records []*claircore.IndexRecord, opts datastore.GetOpts) (map[string][]*claircore.Vulnerability, error) {
4141
ctx = zlog.ContextWithValues(ctx, "component", "internal/vulnstore/postgres/Get")
4242
tx, err := s.pool.Begin(ctx)
4343
if err != nil {

internal/vulnstore/postgres/getupdateoperationdiff.go datastore/postgres/getupdateoperationdiff.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ var (
5555
)
5656
)
5757

58-
func (s *Store) GetUpdateDiff(ctx context.Context, prev, cur uuid.UUID) (*driver.UpdateDiff, error) {
58+
func (s *MatcherStore) GetUpdateDiff(ctx context.Context, prev, cur uuid.UUID) (*driver.UpdateDiff, error) {
5959
// confirmRefs will return a row only if both refs are kind = 'vulnerability'
6060
// therefore, if a pgx.ErrNoRows is returned from this query, at least one
6161
// of the incoming refs is not of kind = 'vulnerability'.

0 commit comments

Comments
 (0)