in registry/datastore/importer.go [1063:1192]
func (imp *Importer) doImport(ctx context.Context, required step, steps ...step) error {
var (
tx Transactor
err error
pre, repos, blobs bool
)
// Assign each valid step to a boolean value. This ensures that we only run a
// particular step once and in the correct order.
steps = append(steps, required)
for _, s := range steps {
switch s {
case preImport:
pre = true
case repoImport:
repos = true
case commonBlobs:
blobs = true
default:
return fmt.Errorf("unknown import step: %v", s)
}
}
var f *os.File
bar := progressbar.NewOptions(-1,
progressbar.OptionShowElapsedTimeOnFinish(),
progressbar.OptionShowDescriptionAtLineEnd(),
progressbar.OptionSetVisibility(imp.showProgressBar),
)
defer bar.Close()
commonBarOptions = append(commonBarOptions, progressbar.OptionSetVisibility(imp.showProgressBar))
if imp.showProgressBar {
fn := fmt.Sprintf("%s-registry-import.log", time.Now().Format(time.RFC3339))
// nolint: gosec // G304
f, err = os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600)
if err != nil {
return fmt.Errorf("opening log file: %w", err)
}
wd, err := os.Getwd()
if err != nil {
return fmt.Errorf("getting working directory: %w", err)
}
// A little hacky, but we can use a progress bar to show the overall import
// progress by printing the bar with different descriptions. Otherwise, the
// progress bars and a regular logger would step over one another.
_ = bar.Add(1) // Give the bar some state so we can print it.
imp.printBar(bar, fmt.Sprintf("registry import starting, detailed log written to: %s", filepath.Join(wd, fn)))
} else {
f = os.Stdout
}
l := log.GetLogger(log.WithContext(ctx), log.WithWriter(f)).WithFields(log.Fields{
"pre_import": pre,
"repository_import": repos,
"common_blobs": blobs,
"dry_run": imp.dryRun,
})
ctx = log.WithLogger(ctx, l)
// Create a single transaction and roll it back at the end for dry runs.
if imp.dryRun {
tx, err = imp.beginTx(ctx)
if err != nil {
return fmt.Errorf("beginning dry run transaction: %w", err)
}
defer tx.Rollback()
}
start := time.Now()
l.Info("starting metadata import")
if pre {
start := time.Now()
imp.printBar(bar, "step one: import manifests")
if err := imp.preImportAllRepositories(ctx); err != nil {
return fmt.Errorf("pre importing all repositories: %w", err)
}
imp.printBar(bar, fmt.Sprintf("step one completed in %s", time.Since(start).Round(time.Second)))
}
if repos {
start := time.Now()
imp.printBar(bar, "step two: import tags")
if err := imp.importAllRepositoriesImpl(ctx); err != nil {
return fmt.Errorf("importing all repositories: %w", err)
}
imp.printBar(bar, fmt.Sprintf("step two completed in %s", time.Since(start).Round(time.Second)))
}
if blobs {
start := time.Now()
imp.printBar(bar, "step three: import blobs")
if err := imp.importBlobsImpl(ctx); err != nil {
return fmt.Errorf("importing blobs: %w", err)
}
imp.printBar(bar, fmt.Sprintf("step three completed in %s", time.Since(start).Round(time.Second)))
}
bar.Describe("registry import complete")
t := time.Since(start).Seconds()
if imp.rowCount {
counters, err := imp.countRows(ctx)
if err != nil {
l.WithError(err).Error("counting table rows")
}
logCounters := make(map[string]any, len(counters))
for t, n := range counters {
logCounters[t] = n
}
l = l.WithFields(logCounters)
}
l.WithFields(log.Fields{"duration_s": t}).Info("metadata import complete")
return err
}