Skip to content

Commit

Permalink
WIP: support for fetch --detect-offline-config
Browse files Browse the repository at this point in the history
In some cases, we want to make a decision in the initramfs
based on whether or not an Ignition config was provided at all.

A good example of this is for live ISOs, we only want
to turn on networking if a config was provided:
https://github.com/coreos/ignition-dracut/issues/94

So the idea is that we'd end up running `ignition fetch --detect-offline-config`
as part of a systemd generator, which could then take futher
steps like pulling in `network-online.target` if a config was
provided.
  • Loading branch information
cgwalters committed Mar 24, 2020
1 parent 2d3ff58 commit 7f529e4
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 2 deletions.
44 changes: 44 additions & 0 deletions internal/exec/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"os"
"time"

"github.com/coreos/ignition/v2/internal/providers/file"

"github.com/coreos/ignition/v2/config"
"github.com/coreos/ignition/v2/config/shared/errors"
latest "github.com/coreos/ignition/v2/config/v3_1_experimental"
Expand Down Expand Up @@ -54,6 +56,8 @@ type Engine struct {
Root string
PlatformConfig platform.Config
Fetcher *resource.Fetcher

DetectOfflineConfig string
}

// Run executes the stage of the given name. It returns true if the stage
Expand All @@ -67,6 +71,26 @@ func (e Engine) Run(stageName string) error {
Ignition: types.Ignition{Version: types.MaxVersion.String()},
}

if stageName == "fetch" && e.DetectOfflineConfig != "" {
var haveConfig bool
var err error
// If we already have a config cache, we're done
if _, err := os.Stat(e.ConfigCache); err != nil {
haveConfig = true
} else {
haveConfig, err = e.detectOfflineConfig()
if err != nil {
return err
}
if haveConfig {
if err := ioutil.WriteFile(e.DetectOfflineConfig, []byte{}, 0644); err != nil {
return err
}
}
// Note early return
return nil
}

systemBaseConfig, r, err := system.FetchBaseConfig(e.Logger)
e.logReport(r)
if err != nil && err != providers.ErrNoProvider {
Expand Down Expand Up @@ -175,6 +199,26 @@ func (e *Engine) acquireConfig() (cfg types.Config, err error) {
return
}

// acquireConfigOffline only looks at config providers which do not
// require networking.
func (e *Engine) detectOfflineConfig() (bool, error) {
offlineFetchers := []providers.FuncDetectConfig{
cmdline.DetectConfig,
file.DetectConfig,
}

for _, fetcher := range offlineFetchers {
exists, err := fetcher(e.Fetcher)
if err != nil {
return false, err
}
if exists {
return true, nil
}
}
return false, nil
}

// fetchProviderConfig returns the externally-provided configuration. It first
// checks to see if the command-line option is present. If so, it uses that
// source for the configuration. If the command-line option is not present, it
Expand Down
7 changes: 6 additions & 1 deletion internal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ func main() {
stage stages.Name
version bool
logToStdout bool

detectOfflineConfig string
}{}

flag.BoolVar(&flags.clearCache, "clear-cache", false, "clear any cached config")
flag.StringVar(&flags.configCache, "config-cache", "/run/ignition.json", "where to cache the config")
flag.DurationVar(&flags.fetchTimeout, "fetch-timeout", exec.DefaultFetchTimeout, "initial duration for which to wait for config")
flag.StringVar(&flags.detectOfflineConfig, "detect-config-provided", "", "If a config is provided, create a file at this path")
flag.Var(&flags.platform, "platform", fmt.Sprintf("current platform. %v", platform.Names()))
flag.StringVar(&flags.root, "root", "/", "root of the filesystem")
flag.Var(&flags.stage, "stage", fmt.Sprintf("execution stage. %v", stages.Names()))
Expand All @@ -60,7 +63,7 @@ func main() {
return
}

if flags.platform == "" {
if flags.platform == "" {
fmt.Fprint(os.Stderr, "'--platform' must be provided\n")
os.Exit(2)
}
Expand Down Expand Up @@ -95,6 +98,8 @@ func main() {
ConfigCache: flags.configCache,
PlatformConfig: platformConfig,
Fetcher: &fetcher,

DetectOfflineConfig: flags.detectOfflineConfig,
}

err = engine.Run(flags.stage.String())
Expand Down
8 changes: 8 additions & 0 deletions internal/providers/cmdline/cmdline.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ const (
cmdlineUrlFlag = "ignition.config.url"
)

func DetectConfig(f *resource.Fetcher) (bool, error) {
url, err := readCmdline(f.Logger)
if err != nil {
return false, err
}
return url != nil, nil
}

func FetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) {
url, err := readCmdline(f.Logger)
if err != nil {
Expand Down
19 changes: 18 additions & 1 deletion internal/providers/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,29 @@ const (
defaultFilename = "config.ign"
)

func FetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) {
func getPath(f *resource.Fetcher) string {
filename := os.Getenv(cfgFilenameEnvVar)
if filename == "" {
filename = defaultFilename
f.Logger.Info("using default filename")
}
return filename
}

func DetectConfig(f *resource.Fetcher) (bool, error) {
filename := getPath(f)
_, err := os.Stat(filename)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return true, nil
}

func FetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) {
filename := getPath(f)
f.Logger.Info("using config file at %q", filename)

rawConfig, err := ioutil.ReadFile(filename)
Expand Down
1 change: 1 addition & 0 deletions internal/providers/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
ErrNoProvider = errors.New("config provider was not online")
)

type FuncDetectConfig func(f *resource.Fetcher) (bool, error)
type FuncFetchConfig func(f *resource.Fetcher) (types.Config, report.Report, error)
type FuncNewFetcher func(logger *log.Logger) (resource.Fetcher, error)
type FuncPostStatus func(stageName string, f resource.Fetcher, e error) error
3 changes: 3 additions & 0 deletions internal/resource/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ type Fetcher struct {
// The logger object to use when logging information.
Logger *log.Logger

// Offline is set when
Offline bool

// client is the http client that will be used when fetching http(s)
// resources. If left nil, one will be created and used, but this means any
// timeouts Ignition was configured to used will be ignored.
Expand Down

0 comments on commit 7f529e4

Please sign in to comment.