PullImage implements code sharing for singularity & podman.
( ctx context.Context, req docker.PullImage, p events.Publisher[docker.Event], wg *waitgroupx.Group, log *logrus.Entry, getPullCommand func(docker.PullImage, string) (string, []string), )
| 111 | |
| 112 | // PullImage implements code sharing for singularity & podman. |
| 113 | func PullImage( |
| 114 | ctx context.Context, |
| 115 | req docker.PullImage, |
| 116 | p events.Publisher[docker.Event], |
| 117 | wg *waitgroupx.Group, |
| 118 | log *logrus.Entry, |
| 119 | getPullCommand func(docker.PullImage, string) (string, []string), |
| 120 | ) (err error) { |
| 121 | if err = p.Publish(ctx, docker.NewBeginStatsEvent(docker.ImagePullStatsKind)); err != nil { |
| 122 | return err |
| 123 | } |
| 124 | defer func() { |
| 125 | if err = p.Publish(ctx, docker.NewEndStatsEvent(docker.ImagePullStatsKind)); err != nil { |
| 126 | log.WithError(err).Warn("did not send image pull done stats") |
| 127 | } |
| 128 | }() |
| 129 | |
| 130 | image := CanonicalizeImage(req.Name) |
| 131 | |
| 132 | uri, err := url.Parse(image) |
| 133 | if err != nil || uri.Scheme == "" { |
| 134 | if err = p.Publish(ctx, docker.NewLogEvent( |
| 135 | model.LogLevelInfo, |
| 136 | fmt.Sprintf("image %s isn't a pullable URI; skipping pull", image), |
| 137 | )); err != nil { |
| 138 | return err |
| 139 | } |
| 140 | return nil |
| 141 | } |
| 142 | |
| 143 | // TODO(DET-9078): Support registry auth. Investigate other auth mechanisms |
| 144 | // with singularity & podman. |
| 145 | command, args := getPullCommand(req, image) |
| 146 | |
| 147 | if err = PprintCommand(ctx, command, args, p, log); err != nil { |
| 148 | return err |
| 149 | } |
| 150 | |
| 151 | cmd := exec.CommandContext(ctx, command, args...) // #nosec G204 'command' is under our control |
| 152 | stdout, err := cmd.StdoutPipe() |
| 153 | if err != nil { |
| 154 | return fmt.Errorf("creating stdout pipe: %w", err) |
| 155 | } |
| 156 | stderr, err := cmd.StderrPipe() |
| 157 | if err != nil { |
| 158 | return fmt.Errorf("creating stderr pipe: %w", err) |
| 159 | } |
| 160 | |
| 161 | // The return codes from `podman pull` aren't super helpful in determining the error, so we |
| 162 | // wrap the publisher and skim logs to see what happened as we ship them. |
| 163 | ignoreErrorsSig := make(chan bool) |
| 164 | checkIgnoreErrors := events.FuncPublisher[docker.Event]( |
| 165 | func(ctx context.Context, t docker.Event) error { |
| 166 | if t.Log != nil && strings.Contains(t.Log.Message, "Image file already exists") { |
| 167 | ignoreErrorsSig <- true |
| 168 | } |
| 169 | return p.Publish(ctx, t) |
| 170 | }, |
nothing calls this directly
no test coverage detected