From 802c800ebcce3e93414d39e64739d5b875611b3d Mon Sep 17 00:00:00 2001 From: Zach Koopmans Date: Mon, 27 Feb 2023 18:40:16 -0800 Subject: [PATCH] Add validate method to runsc config bundles. Validate checks a config bundle map that all flags exist and their values are valid for each flag. PiperOrigin-RevId: 512791071 --- runsc/config/config.go | 17 +++++++++++++ runsc/config/config_test.go | 49 +++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/runsc/config/config.go b/runsc/config/config.go index 3c87a9a71..21ae0533f 100644 --- a/runsc/config/config.go +++ b/runsc/config/config.go @@ -27,6 +27,7 @@ import ( "gvisor.dev/gvisor/pkg/refs" "gvisor.dev/gvisor/pkg/sentry/watchdog" + "gvisor.dev/gvisor/runsc/flag" ) // Config holds configuration that is not part of the runtime spec. @@ -376,6 +377,22 @@ type Bundle map[string]string // It is used as part of an annotation to specify that the user wants to apply a Bundle. type BundleName string +// Validate validates that given flag string values map to actual flags in runsc. +func (b Bundle) Validate() error { + flagSet := flag.NewFlagSet("tmp", flag.ContinueOnError) + RegisterFlags(flagSet) + for key, val := range b { + flag := flagSet.Lookup(key) + if flag == nil { + return fmt.Errorf("unknown flag %q", key) + } + if err := flagSet.Set(key, val); err != nil { + return err + } + } + return nil +} + // MetricMetadata returns key-value pairs that are useful to include in metrics // exported about the sandbox this config represents. func (c *Config) MetricMetadata() map[string]string { diff --git a/runsc/config/config_test.go b/runsc/config/config_test.go index bfdc12ae0..97bd431ab 100644 --- a/runsc/config/config_test.go +++ b/runsc/config/config_test.go @@ -15,6 +15,7 @@ package config import ( + "fmt" "reflect" "strings" "testing" @@ -664,3 +665,51 @@ func TestBundles(t *testing.T) { }) } } + +func TestBundleValidate(t *testing.T) { + defaultVerify := func(err error) error { return err } + for _, tc := range []struct { + name string + bundle Bundle + verify func(err error) error + }{ + { + name: "empty bundle", + bundle: Bundle(map[string]string{}), + verify: defaultVerify, + }, + { + name: "invalid flag bundle", + bundle: Bundle(map[string]string{"not-a-real-flag": "true"}), + verify: func(err error) error { + want := `unknown flag "not-a-real-flag"` + if !strings.Contains(err.Error(), want) { + return fmt.Errorf("mismatch error: got: %q want: %q", err.Error(), want) + } + return nil + }, + }, + { + name: "invalid value", + bundle: Bundle(map[string]string{"debug": "invalid"}), + verify: func(err error) error { + want := `parsing "invalid": invalid syntax` + if !strings.Contains(err.Error(), want) { + return fmt.Errorf("mismatch error: got: %q want: %q", err.Error(), want) + } + return nil + }, + }, + { + name: "valid flag bundle", + bundle: Bundle(map[string]string{"debug": "true"}), + verify: defaultVerify, + }, + } { + t.Run(tc.name, func(t *testing.T) { + if err := tc.verify(tc.bundle.Validate()); err != nil { + t.Fatalf("Validate failed: %v", err) + } + }) + } +}