policy: implement policy logging via progress printer
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
+4
-4
@@ -132,7 +132,7 @@ type policyOpt struct {
|
||||
Files []policy.File
|
||||
FS func() (fs.StatFS, func() error, error)
|
||||
Strict bool
|
||||
LogLevel logrus.Level
|
||||
LogLevel *logrus.Level
|
||||
}
|
||||
|
||||
func withPolicyConfig(defaultPolicy policyOpt, configs []PolicyConfig) ([]policyOpt, error) {
|
||||
@@ -177,7 +177,7 @@ func withPolicyConfig(defaultPolicy policyOpt, configs []PolicyConfig) ([]policy
|
||||
last.Strict = *cfg.Strict
|
||||
}
|
||||
if cfg.LogLevel != nil {
|
||||
last.LogLevel = *cfg.LogLevel
|
||||
last.LogLevel = cfg.LogLevel
|
||||
}
|
||||
}
|
||||
continue
|
||||
@@ -190,13 +190,13 @@ func withPolicyConfig(defaultPolicy policyOpt, configs []PolicyConfig) ([]policy
|
||||
opt.Strict = *last.Strict
|
||||
}
|
||||
if last.LogLevel != nil {
|
||||
opt.LogLevel = *last.LogLevel
|
||||
opt.LogLevel = last.LogLevel
|
||||
}
|
||||
if cfg.Strict != nil {
|
||||
opt.Strict = *cfg.Strict
|
||||
}
|
||||
if cfg.LogLevel != nil {
|
||||
opt.LogLevel = *cfg.LogLevel
|
||||
opt.LogLevel = cfg.LogLevel
|
||||
}
|
||||
opt.FS = defaultPolicy.FS
|
||||
out = append(out, opt)
|
||||
|
||||
+106
-6
@@ -3,9 +3,9 @@ package build
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"maps"
|
||||
"os"
|
||||
"path"
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/containerd/console"
|
||||
@@ -48,6 +49,7 @@ import (
|
||||
"github.com/moby/buildkit/util/gitutil"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/tonistiigi/fsutil"
|
||||
)
|
||||
|
||||
@@ -60,6 +62,79 @@ var sendGitQueryAsInput = sync.OnceValue(func() bool {
|
||||
return false
|
||||
})
|
||||
|
||||
type policyProgressLogger struct {
|
||||
ch chan *client.SolveStatus
|
||||
done chan struct{}
|
||||
dgst digest.Digest
|
||||
started time.Time
|
||||
name string
|
||||
}
|
||||
|
||||
func newPolicyProgressLogger(pw progress.Writer, name string) *policyProgressLogger {
|
||||
if pw == nil {
|
||||
return nil
|
||||
}
|
||||
ch, done := progress.NewChannel(pw)
|
||||
dgst := digest.FromBytes([]byte(identity.NewID()))
|
||||
tm := time.Now()
|
||||
vtx := client.Vertex{
|
||||
Digest: dgst,
|
||||
Name: name,
|
||||
Started: &tm,
|
||||
}
|
||||
ch <- &client.SolveStatus{Vertexes: []*client.Vertex{&vtx}}
|
||||
return &policyProgressLogger{
|
||||
ch: ch,
|
||||
done: done,
|
||||
dgst: dgst,
|
||||
started: tm,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *policyProgressLogger) Log(msg string) {
|
||||
if l == nil || msg == "" {
|
||||
return
|
||||
}
|
||||
if !strings.HasSuffix(msg, "\n") {
|
||||
msg += "\n"
|
||||
}
|
||||
l.ch <- &client.SolveStatus{
|
||||
Logs: []*client.VertexLog{{
|
||||
Vertex: l.dgst,
|
||||
Stream: 1,
|
||||
Data: []byte(msg),
|
||||
Timestamp: time.Now(),
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
func (l *policyProgressLogger) Write(p []byte) (int, error) {
|
||||
if len(p) > 0 {
|
||||
l.Log(string(p))
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (l *policyProgressLogger) Close(err error) {
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
tm := time.Now()
|
||||
vtx := client.Vertex{
|
||||
Digest: l.dgst,
|
||||
Name: l.name,
|
||||
Started: &l.started,
|
||||
Completed: &tm,
|
||||
}
|
||||
if err != nil {
|
||||
vtx.Error = err.Error()
|
||||
}
|
||||
l.ch <- &client.SolveStatus{Vertexes: []*client.Vertex{&vtx}}
|
||||
close(l.ch)
|
||||
<-l.done
|
||||
}
|
||||
|
||||
func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *Options, bopts gateway.BuildOpts, cfg *confutil.Config, pw progress.Writer, docker *dockerutil.Client) (_ *client.SolveOpt, release func(), err error) {
|
||||
nodeDriver := node.Driver
|
||||
defers := make([]func(), 0, 2)
|
||||
@@ -347,14 +422,39 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *O
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var policyFiles []string
|
||||
for _, popt := range popts {
|
||||
for _, f := range popt.Files {
|
||||
if f.Filename != "" {
|
||||
policyFiles = append(policyFiles, f.Filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
var policyLogger *policyProgressLogger
|
||||
if len(policyFiles) > 0 {
|
||||
policyLogger = newPolicyProgressLogger(pw, fmt.Sprintf("loading policies %s", strings.Join(policyFiles, ", ")))
|
||||
}
|
||||
if policyLogger != nil {
|
||||
defers = append(defers, func() {
|
||||
policyLogger.Close(nil)
|
||||
})
|
||||
}
|
||||
var cbs []policysession.PolicyCallback
|
||||
for _, popt := range popts {
|
||||
policyLevel := logrus.GetLevel()
|
||||
if popt.LogLevel != nil {
|
||||
policyLevel = *popt.LogLevel
|
||||
}
|
||||
logf := func(level logrus.Level, msg string) {
|
||||
if policyLogger == nil || level > policyLevel {
|
||||
return
|
||||
}
|
||||
policyLogger.Log(msg)
|
||||
}
|
||||
p := policy.NewPolicy(policy.Opt{
|
||||
Files: popt.Files,
|
||||
Env: env,
|
||||
Log: func(msg string) {
|
||||
log.Printf("[policy] %s", msg)
|
||||
},
|
||||
Files: popt.Files,
|
||||
Env: env,
|
||||
Log: logf,
|
||||
FS: opt.Inputs.policy.FS,
|
||||
VerifierProvider: policy.SignatureVerifier(cfg),
|
||||
})
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestWithPolicyConfigDefaults(t *testing.T) {
|
||||
require.Len(t, out, 1)
|
||||
require.Equal(t, defaultPolicy.Files, out[0].Files)
|
||||
require.False(t, out[0].Strict)
|
||||
require.Equal(t, logrus.Level(0), out[0].LogLevel)
|
||||
require.Nil(t, out[0].LogLevel)
|
||||
require.NotNil(t, out[0].FS)
|
||||
}
|
||||
|
||||
@@ -54,11 +54,10 @@ func TestWithPolicyConfigDisabled(t *testing.T) {
|
||||
})
|
||||
require.Error(t, err)
|
||||
|
||||
out, err := withPolicyConfig(policyOpt{}, []PolicyConfig{
|
||||
_, err = withPolicyConfig(policyOpt{}, []PolicyConfig{
|
||||
{Disabled: true, LogLevel: levelPtr(logrus.WarnLevel)},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, out)
|
||||
require.Error(t, err)
|
||||
|
||||
_, err = withPolicyConfig(policyOpt{}, []PolicyConfig{
|
||||
{Disabled: true},
|
||||
@@ -66,7 +65,7 @@ func TestWithPolicyConfigDisabled(t *testing.T) {
|
||||
})
|
||||
require.Error(t, err)
|
||||
|
||||
out, err = withPolicyConfig(policyOpt{}, []PolicyConfig{
|
||||
out, err := withPolicyConfig(policyOpt{}, []PolicyConfig{
|
||||
{Disabled: true},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -104,7 +103,8 @@ func TestWithPolicyConfigStrictAndLogLevel(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, out, 1)
|
||||
require.True(t, out[0].Strict)
|
||||
require.Equal(t, logrus.WarnLevel, out[0].LogLevel)
|
||||
require.NotNil(t, out[0].LogLevel)
|
||||
require.Equal(t, logrus.WarnLevel, *out[0].LogLevel)
|
||||
}
|
||||
|
||||
// TestWithPolicyConfigStrictIgnoredWithoutPolicy ensures strict without any policy produces no entries.
|
||||
@@ -135,7 +135,8 @@ func TestWithPolicyConfigMultipleFilesAndOverrides(t *testing.T) {
|
||||
require.Equal(t, "default.rego", out[0].Files[0].Filename)
|
||||
require.Equal(t, "a.rego", out[1].Files[0].Filename)
|
||||
require.True(t, out[1].Strict)
|
||||
require.Equal(t, logrus.WarnLevel, out[1].LogLevel)
|
||||
require.NotNil(t, out[1].LogLevel)
|
||||
require.Equal(t, logrus.WarnLevel, *out[1].LogLevel)
|
||||
require.Equal(t, "b.rego", out[2].Files[0].Filename)
|
||||
require.True(t, out[2].Strict)
|
||||
require.NotNil(t, out[1].FS)
|
||||
|
||||
Reference in New Issue
Block a user