github.com/quay/claircore@v1.5.28/datastore/postgres/recordupdatetime.go (about) 1 package postgres 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/jackc/pgx/v4/pgxpool" 9 "github.com/quay/claircore/libvuln/driver" 10 "github.com/quay/zlog" 11 ) 12 13 // recordUpdaterStatus records that an updater is up to date with vulnerabilities at this time 14 // inserts an updater with last update timestamp, or updates an existing updater with a new update time 15 func recordUpdaterStatus(ctx context.Context, pool *pgxpool.Pool, updaterName string, updateTime time.Time, fingerprint driver.Fingerprint, updaterError error) error { 16 const ( 17 // upsertSuccessfulUpdate inserts or updates a record of the last time an updater successfully checked for new vulns 18 upsertSuccessfulUpdate = `INSERT INTO updater_status ( 19 updater_name, 20 last_attempt, 21 last_success, 22 last_run_succeeded, 23 last_attempt_fingerprint 24 ) VALUES ( 25 $1, 26 $2, 27 $2, 28 'true', 29 $3 30 ) 31 ON CONFLICT (updater_name) DO UPDATE 32 SET last_attempt = $2, 33 last_success = $2, 34 last_run_succeeded = 'true', 35 last_attempt_fingerprint = $3 36 RETURNING updater_name;` 37 38 // upsertFailedUpdate inserts or updates a record of the last time an updater attempted but failed to check for new vulns 39 upsertFailedUpdate = `INSERT INTO updater_status ( 40 updater_name, 41 last_attempt, 42 last_run_succeeded, 43 last_attempt_fingerprint, 44 last_error 45 ) VALUES ( 46 $1, 47 $2, 48 'false', 49 $3, 50 $4 51 ) 52 ON CONFLICT (updater_name) DO UPDATE 53 SET last_attempt = $2, 54 last_run_succeeded = 'false', 55 last_attempt_fingerprint = $3, 56 last_error = $4 57 RETURNING updater_name;` 58 ) 59 60 ctx = zlog.ContextWithValues(ctx, 61 "component", "internal/vulnstore/postgres/recordUpdaterStatus") 62 63 tx, err := pool.Begin(ctx) 64 if err != nil { 65 return fmt.Errorf("unable to start transaction: %w", err) 66 } 67 defer tx.Rollback(ctx) 68 69 var returnedUpdaterName string 70 71 if updaterError == nil { 72 zlog.Debug(ctx). 73 Str("updater", updaterName). 74 Msg("recording successful update") 75 _, err := tx.Exec(ctx, upsertSuccessfulUpdate, updaterName, updateTime, fingerprint) 76 if err != nil { 77 return fmt.Errorf("failed to upsert successful updater status: %w", err) 78 } 79 } else { 80 zlog.Debug(ctx). 81 Str("updater", updaterName). 82 Msg("recording failed update") 83 if err := tx.QueryRow(ctx, upsertFailedUpdate, updaterName, updateTime, fingerprint, updaterError.Error()).Scan(&returnedUpdaterName); err != nil { 84 return fmt.Errorf("failed to upsert failed updater status: %w", err) 85 } 86 } 87 88 if err := tx.Commit(ctx); err != nil { 89 return fmt.Errorf("failed to commit transaction: %w", err) 90 } 91 92 zlog.Debug(ctx). 93 Str("updater", updaterName). 94 Msg("updater status stored in database") 95 96 return nil 97 } 98 99 // recordUpdaterSetStatus records that all updaters for a single updater set are up to date with vulnerabilities at this time 100 // updates all existing updaters from this updater set with the new update time 101 // the updater set parameter passed needs to match the prefix of the given updater set name format 102 func recordUpdaterSetStatus(ctx context.Context, pool *pgxpool.Pool, updaterSet string, updateTime time.Time) error { 103 const ( 104 update = `UPDATE updater_status 105 SET last_attempt = $1, 106 last_success = $1, 107 last_run_succeeded = 'true' 108 WHERE updater_name like $2 || '%';` 109 ) 110 111 ctx = zlog.ContextWithValues(ctx, 112 "component", "internal/vulnstore/postgres/recordUpdaterSetStatus") 113 114 tx, err := pool.Begin(ctx) 115 if err != nil { 116 return fmt.Errorf("unable to start transaction: %w", err) 117 } 118 defer tx.Rollback(ctx) 119 120 tag, err := tx.Exec(ctx, update, updateTime, updaterSet) 121 if err != nil { 122 return fmt.Errorf("failed to update updater statuses for updater set %s: %w", updaterSet, err) 123 } 124 125 if err := tx.Commit(ctx); err != nil { 126 return fmt.Errorf("failed to commit transaction: %w", err) 127 } 128 129 zlog.Debug(ctx). 130 Str("factory", updaterSet). 131 Int64("rowsAffected", tag.RowsAffected()). 132 Msg("status updated for factory updaters") 133 134 return nil 135 }