@@ -367,6 +367,15 @@ func (b *lockedBuffer) Tail(maxBytes int) string {
367367 return string (content [len (content )- maxBytes :])
368368}
369369
370+ // custodianCachePath returns a writable path for c7n's resource cache file.
371+ // c7n defaults to ~/.cache/cloud-custodian.cache, which is unwritable when the
372+ // container runs with a read-only root filesystem and no writable HOME.
373+ // os.TempDir resolves to $TMPDIR or /tmp; the agent deployment mounts /tmp as a
374+ // writable emptyDir, so the cache lands somewhere always writable and ephemeral.
375+ func custodianCachePath () string {
376+ return filepath .Join (os .TempDir (), "cloud-custodian.cache" )
377+ }
378+
370379func custodianDiagnosticInterval (timeout time.Duration ) time.Duration {
371380 if timeout <= 0 {
372381 return custodianWatchInterval
@@ -490,7 +499,12 @@ func (e *CommandCustodianExecutor) Execute(ctx context.Context, req CustodianExe
490499 if req .Verbose {
491500 args = append (args , "-v" )
492501 }
493- args = append (args , "--dryrun" , "-s" , req .OutputDir , policyPath )
502+ // Pin c7n's resource cache to a writable, ephemeral location. By default
503+ // c7n writes to ~/.cache/cloud-custodian.cache; with no HOME set and a
504+ // read-only root filesystem that makedirs fails with "Read-only file
505+ // system". os.TempDir honors TMPDIR and otherwise resolves to /tmp, which
506+ // the agent deployment mounts as a writable emptyDir.
507+ args = append (args , "--dryrun" , "-s" , req .OutputDir , "--cache" , custodianCachePath (), policyPath )
494508 if strings .EqualFold (req .Check .Provider , "aws" ) {
495509 for _ , region := range regions {
496510 args = append (args , "--region" , region )
0 commit comments