Repository navigation
Expand file tree
/
Copy pathhandler.go
More file actions
164 lines (143 loc) · 5.2 KB
/
Copy pathhandler.go
File metadata and controls
164 lines (143 loc) · 5.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package reprocessor
import (
"github.com/pkg/errors"
"github.com/stackrox/rox/generated/internalapi/central"
"github.com/stackrox/rox/pkg/centralsensor"
"github.com/stackrox/rox/pkg/concurrency"
"github.com/stackrox/rox/pkg/logging"
"github.com/stackrox/rox/sensor/common"
"github.com/stackrox/rox/sensor/common/admissioncontroller"
"github.com/stackrox/rox/sensor/common/centralcaps"
"github.com/stackrox/rox/sensor/common/detector"
"github.com/stackrox/rox/sensor/common/image/cache"
"github.com/stackrox/rox/sensor/common/message"
"github.com/stackrox/rox/sensor/common/unimplemented"
)
var (
log = logging.LoggerForModule()
)
// Handler handles request to reprocess deployment (sent by Central).
//
//go:generate mockgen-wrapper
type Handler interface {
common.SensorComponent
ProcessReprocessDeployments(*central.ReprocessDeployment) error
ProcessInvalidateImageCache(*central.InvalidateImageCache) error
ProcessRefreshImageCacheTTL(*central.RefreshImageCacheTTL) error
}
// NewHandler returns a new instance of a deployment reprocessor.
func NewHandler(admCtrlSettingsMgr admissioncontroller.SettingsManager, detector detector.Detector, imageCache cache.Image) Handler {
return &handlerImpl{
admCtrlSettingsMgr: admCtrlSettingsMgr,
detector: detector,
imageCache: imageCache,
stopSig: concurrency.NewErrorSignal(),
}
}
type handlerImpl struct {
unimplemented.Receiver
admCtrlSettingsMgr admissioncontroller.SettingsManager
detector detector.Detector
imageCache cache.Image
stopSig concurrency.ErrorSignal
}
func (h *handlerImpl) Name() string {
return "reprocessor.handlerImpl"
}
func (h *handlerImpl) Start() error {
return nil
}
func (h *handlerImpl) Stop() {
h.stopSig.Signal()
}
func (h *handlerImpl) Notify(common.SensorComponentEvent) {}
func (h *handlerImpl) Capabilities() []centralsensor.SensorCapability {
// A new sensor capability to reprocess deployment has not been added. In case of mismatched upgrades,
// the re-processing is discarded, which is fine.
return []centralsensor.SensorCapability{
centralsensor.TargetedImageCacheInvalidation,
}
}
func (h *handlerImpl) ProcessReprocessDeployments(req *central.ReprocessDeployment) error {
log.Debug("Received request to reprocess deployments from Central")
select {
case <-h.stopSig.Done():
return errors.Wrap(h.stopSig.Err(), "could not fulfill re-process deployment(s) request")
default:
go h.detector.ReprocessDeployments(req.GetDeploymentIds()...)
}
return nil
}
func (h *handlerImpl) ProcessInvalidateImageCache(req *central.InvalidateImageCache) error {
log.Debug("Received request to invalidate image caches")
select {
case <-h.stopSig.Done():
return errors.Wrap(h.stopSig.Err(), "could not fulfill invalidate image cache request")
default:
h.admCtrlSettingsMgr.InvalidateImageCache(req.GetImageKeys())
// Each ImageKey may produce up to 2 cache keys (digest-derived + full name).
keysToDelete := make([]cache.Key, 0, len(req.GetImageKeys())*2)
for _, image := range req.GetImageKeys() {
keysToDelete = append(keysToDelete, cacheKeysToInvalidate(image)...)
}
h.imageCache.Remove(keysToDelete...)
}
return nil
}
func (h *handlerImpl) ProcessRefreshImageCacheTTL(req *central.RefreshImageCacheTTL) error {
log.Debug("Received request to refresh image cache TTLs")
select {
case <-h.stopSig.Done():
return errors.Wrap(h.stopSig.Err(), "could not fulfill refresh image cache TTL request")
default:
// Unlike invalidation, refresh intentionally touches only the
// digest-derived key and does not touch name-based entries.
// Name-based entries may refer to images with mutable tags
// (e.g. "latest"); refreshing them would delay expiry and
// risk serving stale data when the tag points to a new image.
for _, image := range req.GetImageKeys() {
if key := cacheKeyFromImageKey(image); key != "" {
h.imageCache.Touch(key)
}
}
}
return nil
}
// cacheKeyFromImageKey resolves the cache key from an ImageKey
// proto, applying the V2/V1/fullName precedence based on the FlattenImageData capability.
func cacheKeyFromImageKey(imageKey *central.ImageKey) cache.Key {
var key string
if centralcaps.Has(centralsensor.FlattenImageData) {
key = imageKey.GetImageIdV2()
} else {
key = imageKey.GetImageId()
}
if key == "" {
key = imageKey.GetImageFullName()
}
return cache.Key(key)
}
// cacheKeysToInvalidate returns all possible cache keys for an ImageKey.
// Images may be cached under either a digest-derived key (V2 UUID5 or raw
// digest) or the full image name, depending on whether the deployment's
// container image had a digest when it was first cached. Both keys must
// be invalidated to avoid stale entries.
func cacheKeysToInvalidate(imageKey *central.ImageKey) []cache.Key {
var keys []cache.Key
if centralcaps.Has(centralsensor.FlattenImageData) {
if id := imageKey.GetImageIdV2(); id != "" {
keys = append(keys, cache.Key(id))
}
} else {
if id := imageKey.GetImageId(); id != "" {
keys = append(keys, cache.Key(id))
}
}
if fullName := imageKey.GetImageFullName(); fullName != "" {
keys = append(keys, cache.Key(fullName))
}
return keys
}
func (h *handlerImpl) ResponsesC() <-chan *message.ExpiringMessage {
return nil
}