github.com/secure-build/gitlab-runner@v12.5.0+incompatible/executors/docker/executor_docker_command.go (about)

     1  package docker
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"sync"
     7  
     8  	"github.com/docker/docker/api/types"
     9  
    10  	"gitlab.com/gitlab-org/gitlab-runner/common"
    11  	"gitlab.com/gitlab-org/gitlab-runner/executors"
    12  	"gitlab.com/gitlab-org/gitlab-runner/executors/docker/internal/volumes/parser"
    13  )
    14  
    15  type commandExecutor struct {
    16  	executor
    17  	buildContainer *types.ContainerJSON
    18  	sync.Mutex
    19  }
    20  
    21  func (s *commandExecutor) getBuildContainer() *types.ContainerJSON {
    22  	s.Lock()
    23  	defer s.Unlock()
    24  
    25  	return s.buildContainer
    26  }
    27  
    28  func (s *commandExecutor) Prepare(options common.ExecutorPrepareOptions) error {
    29  	err := s.executor.Prepare(options)
    30  	if err != nil {
    31  		return err
    32  	}
    33  
    34  	s.Debugln("Starting Docker command...")
    35  
    36  	if len(s.BuildShell.DockerCommand) == 0 {
    37  		return errors.New("Script is not compatible with Docker")
    38  	}
    39  
    40  	_, err = s.getPrebuiltImage()
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	_, err = s.getBuildImage()
    46  	if err != nil {
    47  		return err
    48  	}
    49  	return nil
    50  }
    51  
    52  func (s *commandExecutor) requestNewPredefinedContainer() (*types.ContainerJSON, error) {
    53  	prebuildImage, err := s.getPrebuiltImage()
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	buildImage := common.Image{
    59  		Name: prebuildImage.ID,
    60  	}
    61  
    62  	containerJSON, err := s.createContainer("predefined", buildImage, s.helperImageInfo.Cmd, []string{prebuildImage.ID})
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	return containerJSON, err
    68  }
    69  
    70  func (s *commandExecutor) requestBuildContainer() (*types.ContainerJSON, error) {
    71  	s.Lock()
    72  	defer s.Unlock()
    73  
    74  	if s.buildContainer == nil {
    75  		var err error
    76  
    77  		// Start build container which will run actual build
    78  		s.buildContainer, err = s.createContainer("build", s.Build.Image, s.BuildShell.DockerCommand, []string{})
    79  		if err != nil {
    80  			return nil, err
    81  		}
    82  	}
    83  
    84  	return s.buildContainer, nil
    85  }
    86  
    87  func (s *commandExecutor) Run(cmd common.ExecutorCommand) error {
    88  	var runOn *types.ContainerJSON
    89  	var err error
    90  	if cmd.Predefined {
    91  		runOn, err = s.requestNewPredefinedContainer()
    92  	} else {
    93  		runOn, err = s.requestBuildContainer()
    94  	}
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	s.Debugln("Executing on", runOn.Name, "the", cmd.Script)
   100  
   101  	s.SetCurrentStage(DockerExecutorStageRun)
   102  
   103  	return s.watchContainer(cmd.Context, runOn.ID, bytes.NewBufferString(cmd.Script))
   104  }
   105  
   106  func init() {
   107  	options := executors.ExecutorOptions{
   108  		DefaultCustomBuildsDirEnabled: true,
   109  		DefaultBuildsDir:              "/builds",
   110  		DefaultCacheDir:               "/cache",
   111  		SharedBuildsDir:               false,
   112  		Shell: common.ShellScriptInfo{
   113  			Shell:         "bash",
   114  			Type:          common.NormalShell,
   115  			RunnerCommand: "/usr/bin/gitlab-runner-helper",
   116  		},
   117  		ShowHostname: true,
   118  		Metadata: map[string]string{
   119  			metadataOSType: osTypeLinux,
   120  		},
   121  	}
   122  
   123  	creator := func() common.Executor {
   124  		e := &commandExecutor{
   125  			executor: executor{
   126  				AbstractExecutor: executors.AbstractExecutor{
   127  					ExecutorOptions: options,
   128  				},
   129  				volumeParser: parser.NewLinuxParser(),
   130  			},
   131  		}
   132  		e.SetCurrentStage(common.ExecutorStageCreated)
   133  		return e
   134  	}
   135  
   136  	featuresUpdater := func(features *common.FeaturesInfo) {
   137  		features.Variables = true
   138  		features.Image = true
   139  		features.Services = true
   140  		features.Session = true
   141  		features.Terminal = true
   142  	}
   143  
   144  	common.RegisterExecutor("docker", executors.DefaultExecutorProvider{
   145  		Creator:          creator,
   146  		FeaturesUpdater:  featuresUpdater,
   147  		DefaultShellName: options.Shell.Shell,
   148  	})
   149  }