diff options
Diffstat (limited to 'pkg/hooks/exec/runtimeconfigfilter.go')
-rw-r--r-- | pkg/hooks/exec/runtimeconfigfilter.go | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/pkg/hooks/exec/runtimeconfigfilter.go b/pkg/hooks/exec/runtimeconfigfilter.go new file mode 100644 index 000000000..c6971f680 --- /dev/null +++ b/pkg/hooks/exec/runtimeconfigfilter.go @@ -0,0 +1,68 @@ +package exec + +import ( + "bytes" + "context" + "encoding/json" + "reflect" + "time" + + "github.com/davecgh/go-spew/spew" + spec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" + "github.com/pmezard/go-difflib/difflib" + "github.com/sirupsen/logrus" +) + +var spewConfig = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, +} + +// RuntimeConfigFilter calls a series of hooks. But instead of +// passing container state on their standard input, +// RuntimeConfigFilter passes the proposed runtime configuration (and +// reads back a possibly-altered form from their standard output). +func RuntimeConfigFilter(ctx context.Context, hooks []spec.Hook, config *spec.Spec, postKillTimeout time.Duration) (hookErr, err error) { + data, err := json.Marshal(config) + for i, hook := range hooks { + var stdout bytes.Buffer + hookErr, err = Run(ctx, &hook, data, &stdout, nil, postKillTimeout) + if err != nil { + return hookErr, err + } + + data = stdout.Bytes() + var newConfig spec.Spec + err = json.Unmarshal(data, &newConfig) + if err != nil { + logrus.Debugf("invalid JSON from config-filter hook %d:\n%s", i, string(data)) + return nil, errors.Wrapf(err, "unmarshal output from config-filter hook %d", i) + } + + if !reflect.DeepEqual(config, &newConfig) { + old := spewConfig.Sdump(config) + new := spewConfig.Sdump(&newConfig) + diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(old), + B: difflib.SplitLines(new), + FromFile: "Old", + FromDate: "", + ToFile: "New", + ToDate: "", + Context: 1, + }) + if err == nil { + logrus.Debugf("precreate hook %d made configuration changes:\n%s", i, diff) + } else { + logrus.Warnf("precreate hook %d made configuration changes, but we could not compute a diff: %v", i, err) + } + } + + *config = newConfig + } + + return nil, nil +} |