diff --git a/internal/exec/engine.go b/internal/exec/engine.go index 8e2ad1327a..1f90a6fcc2 100644 --- a/internal/exec/engine.go +++ b/internal/exec/engine.go @@ -24,6 +24,7 @@ import ( "net/url" "os" "strconv" + "strings" "time" "github.com/coreos/go-systemd/v22/journal" @@ -108,7 +109,7 @@ func (e Engine) Run(stageName string) error { e.Fetcher.Offline = true } - cfg, err := e.acquireConfig() + cfg, err := e.acquireConfig(stageName) if err == resource.ErrNeedNet && stageName == "fetch-offline" { err = SignalNeedNet() if err != nil { @@ -162,11 +163,30 @@ func logStructuredJournalEntry(config string, src string, isReferenced bool) err return nil } -// acquireConfig returns the configuration, first checking a local cache -// before attempting to fetch it from the provider. -func (e *Engine) acquireConfig() (cfg types.Config, err error) { +// acquireConfig will perform differently based on the stage it is being +// called from. In fetch stages it will attempt to fetch the provider +// config (writing an empty provider config if it is empty). In all other +// stages it will attempt to fetch from the local cache only. +func (e *Engine) acquireConfig(stageName string) (cfg types.Config, err error) { + switch { + case strings.HasPrefix(stageName, "fetch"): + cfg, err = e.acquireProviderConfig() + if err == errors.ErrEmpty { + e.Logger.Info("%v: provider config was empty, writing empty cache config", err) + if err = renameio.WriteFile(e.ConfigCache, []byte("{}"), 0640); err != nil { + e.Logger.Crit("failed to write empty cached config: %v", err) + } + } + break + default: + cfg, err = e.acquireCachedConfig() + } + return +} - // First try read the config @ e.ConfigCache. +// acquireCachedConfig returns the configuration from a local cache if +// available +func (e *Engine) acquireCachedConfig() (cfg types.Config, err error) { b, err := ioutil.ReadFile(e.ConfigCache) if err == nil { if err = json.Unmarshal(b, &cfg); err != nil { @@ -179,9 +199,13 @@ func (e *Engine) acquireConfig() (cfg types.Config, err error) { e.Logger.Crit("failed to update timeouts and CAs for fetcher: %v", err) return } - return } + return +} +// acquireProviderConfig attempts to fetch the configuration from the +// provider. +func (e *Engine) acquireProviderConfig() (cfg types.Config, err error) { // Create a new http client and fetcher with the timeouts set via the flags, // since we don't have a config with timeout values we can use timeout := int(e.FetchTimeout.Seconds()) @@ -222,7 +246,7 @@ func (e *Engine) acquireConfig() (cfg types.Config, err error) { } // Populate the config cache. - b, err = json.Marshal(cfg) + b, err := json.Marshal(cfg) if err != nil { e.Logger.Crit("failed to marshal cached config: %v", err) return diff --git a/tests/blackbox_test.go b/tests/blackbox_test.go index 189453e2b7..b7c240febd 100644 --- a/tests/blackbox_test.go +++ b/tests/blackbox_test.go @@ -279,6 +279,10 @@ func outer(t *testing.T, test types.Test, negativeTests bool) error { appendEnv = append(appendEnv, "IGNITION_SYSTEM_CONFIG_DIR="+systemConfigDir) if !negativeTests { + if err := runIgnition(t, ctx, "fetch", "", tmpDirectory, appendEnv); err != nil { + return err + } + if err := runIgnition(t, ctx, "disks", "", tmpDirectory, appendEnv); err != nil { return err } @@ -315,6 +319,10 @@ func outer(t *testing.T, test types.Test, negativeTests bool) error { } return nil } else { + if err := runIgnition(t, ctx, "fetch", "", tmpDirectory, appendEnv); err != nil { + return nil // error is expected + } + if err := runIgnition(t, ctx, "disks", "", tmpDirectory, appendEnv); err != nil { return nil // error is expected } diff --git a/tests/filesystem.go b/tests/filesystem.go index f6d711ca99..dcf0f2fc5c 100644 --- a/tests/filesystem.go +++ b/tests/filesystem.go @@ -152,7 +152,7 @@ func umountPartition(p *types.Partition) error { // returns true if no error, false if error func runIgnition(t *testing.T, ctx context.Context, stage, root, cwd string, appendEnv []string) error { - args := []string{"-clear-cache", "-platform", "file", "-stage", stage, + args := []string{"-platform", "file", "-stage", stage, "-root", root, "-log-to-stdout", "--config-cache", filepath.Join(cwd, "ignition.json")} cmd := exec.CommandContext(ctx, "ignition", args...) t.Log("ignition", args)