func newContainerCommandExecutor()

in command-runner/pkg/runner/container_command_executor.go [39:147]


func newContainerCommandExecutor(ctx context.Context, params *newContainerCommandExecutorParams) (commandExecutor, error) {
	containerName := fmt.Sprintf("codecatalyst-%s", regexp.MustCompile(`[^a-zA-Z0-9_.-]`).ReplaceAllString(params.ID, "_"))
	containerName = strings.ToLower(containerName)

	var imagePrep common.Executor
	var image string
	platform := ""

	if i, found := strings.CutPrefix(params.Image, "docker://"); found {
		// pull image from registry
		image = i
	} else {
		// local docker build
		dockerfilePath := params.Image
		if !filepath.IsAbs(dockerfilePath) {
			dockerfilePath = filepath.Join(params.WorkingDir, params.Image)
		}
		_, err := os.Stat(dockerfilePath)
		if err != nil {
			return nil, err
		}
		image = fmt.Sprintf("%s:%s", containerName, "latest")
		exists, err := params.ContainerService.ImageExistsLocally(ctx, image, platform)
		log.Ctx(ctx).Debug().Msgf("%s exists? %v", image, exists)
		if err != nil {
			log.Ctx(ctx).Error().Err(err).Msg("unable to check for local image")
		}
		if params.Reuse && exists {
			imagePrep = func(ctx context.Context) error { return nil }
		} else {
			imagePrep = params.ContainerService.BuildImage(types.BuildImageInput{
				ContextDir: filepath.Dir(dockerfilePath),
				Dockerfile: filepath.Base(dockerfilePath),
				ImageTag:   image,
				Platform:   platform,
			}).TraceRegion("image-build")
		}
	}

	env, containerDefaultDir, err := setupEnvironmentVariables(params.Env)
	if err != nil {
		return nil, err
	}

	mceDir, err := setupMceDir(env, containerDefaultDir)
	if err != nil {
		return nil, err
	}
	binds := []string{
		fmt.Sprintf("%s:%s", "/var/run/docker.sock", "/var/run/docker.sock"),
		fmt.Sprintf("%s:%s", mceDir, "/tmp/mce"),
	}

	for _, filemap := range params.FileMaps {
		srcPath := resolvePath(filemap.SourcePath, params.WorkingDir)
		targetPath := resolvePath(filemap.TargetPath, containerSourceDir)
		if filemap.Type == FileMapTypeBind {
			binds = append(binds,
				fmt.Sprintf(
					"%s:%s%s",
					srcPath,
					targetPath,
					bindModifiers(),
				),
			)
		}
	}

	log.Ctx(ctx).Debug().Msgf("Container binds: %#v", binds)
	log.Ctx(ctx).Debug().Msgf("Container env: %#v", env)

	actionContainer := params.ContainerService.NewContainer(types.NewContainerInput{
		Image:      image,
		Name:       containerName,
		Stdout:     params.Stdout,
		Stderr:     params.Stderr,
		Env:        env,
		WorkingDir: containerDefaultDir,
		Binds:      binds,
		Entrypoint: params.Entrypoint,
	})

	copyExecutors, closeExecutors, err := setupCopyAndCloseExecutors(actionContainer, params.WorkingDir, params.FileMaps)
	if err != nil {
		return nil, err
	}

	if imagePrep == nil {
		imagePrep = actionContainer.Pull(true).TraceRegion("image-pull")
	}

	if err := common.NewPipelineExecutor(
		imagePrep,
		actionContainer.Remove().IfBool(!params.Reuse),
		actionContainer.Create(nil, nil).TraceRegion("container-create"),
		common.NewPipelineExecutor(copyExecutors...).TraceRegion("container-copy"),
		actionContainer.Start(false).TraceRegion("container-start"),
	)(ctx); err != nil {
		return nil, fmt.Errorf("unable to create container executor: %w", err)
	}

	return &containerCommandExecutor{
		Container:       actionContainer,
		ReuseContainers: params.Reuse,
		CloseExecutors:  closeExecutors,
		mceDir:          mceDir,
		ctx:             ctx,
	}, nil
}