github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/worker/container_spec.go (about)

     1  package worker
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"code.cloudfoundry.org/garden"
     8  	"github.com/pf-qiu/concourse/v6/atc/db"
     9  	"github.com/pf-qiu/concourse/v6/atc/runtime"
    10  )
    11  
    12  type WorkerSpec struct {
    13  	Platform     string
    14  	ResourceType string
    15  	Tags         []string
    16  	TeamID       int
    17  }
    18  
    19  type ContainerSpec struct {
    20  	TeamID    int
    21  	ImageSpec ImageSpec
    22  	Env       []string
    23  	Type      db.ContainerType
    24  
    25  	// Working directory for processes run in the container.
    26  	Dir string
    27  
    28  	// artifacts configured as usable. The key reps the mount path of the input artifact
    29  	// and value is the artifact itself
    30  	ArtifactByPath map[string]runtime.Artifact
    31  
    32  	// Inputs to provide to the container. Inputs with a volume local to the
    33  	// selected worker will be made available via a COW volume; others will be
    34  	// streamed.
    35  	Inputs []InputSource
    36  
    37  	// Outputs for which volumes should be created and mounted into the container.
    38  	Outputs OutputPaths
    39  
    40  	// Resource limits to be set on the container when creating in garden.
    41  	Limits ContainerLimits
    42  
    43  	// Local volumes to bind mount directly to the container when creating in garden.
    44  	BindMounts []BindMountSource
    45  
    46  	// Optional user to run processes as. Overwrites the one specified in the docker image.
    47  	User string
    48  }
    49  
    50  // The below methods cause ContainerSpec to fulfill the
    51  // go.opentelemetry.io/otel/api/propagation.HTTPSupplier interface
    52  
    53  func (cs *ContainerSpec) Get(key string) string {
    54  	for _, env := range cs.Env {
    55  		assignment := strings.SplitN("=", env, 2)
    56  		if assignment[0] == strings.ToUpper(key) {
    57  			return assignment[1]
    58  		}
    59  	}
    60  	return ""
    61  }
    62  
    63  func (cs *ContainerSpec) Set(key string, value string) {
    64  	varName := strings.ToUpper(key)
    65  	envVar := varName + "=" + value
    66  	for i, env := range cs.Env {
    67  		if strings.SplitN("=", env, 2)[0] == varName {
    68  			cs.Env[i] = envVar
    69  			return
    70  		}
    71  	}
    72  	cs.Env = append(cs.Env, envVar)
    73  }
    74  
    75  //go:generate counterfeiter . InputSource
    76  
    77  type InputSource interface {
    78  	Source() ArtifactSource
    79  	DestinationPath() string
    80  }
    81  
    82  //go:generate counterfeiter . BindMountSource
    83  
    84  type BindMountSource interface {
    85  	VolumeOn(Worker) (garden.BindMount, bool, error)
    86  }
    87  
    88  // OutputPaths is a mapping from output name to its path in the container.
    89  type OutputPaths map[string]string
    90  
    91  type ImageSpec struct {
    92  	ResourceType        string
    93  	ImageURL            string
    94  	ImageArtifactSource StreamableArtifactSource
    95  	ImageArtifact       runtime.Artifact
    96  	Privileged          bool
    97  }
    98  
    99  type ContainerLimits struct {
   100  	CPU    *uint64
   101  	Memory *uint64
   102  }
   103  
   104  type inputSource struct {
   105  	source ArtifactSource
   106  	path   string
   107  }
   108  
   109  func (src inputSource) Source() ArtifactSource {
   110  	return src.source
   111  }
   112  
   113  func (src inputSource) DestinationPath() string {
   114  	return src.path
   115  }
   116  
   117  var GardenLimitDefault = uint64(0)
   118  
   119  func (cl ContainerLimits) ToGardenLimits() garden.Limits {
   120  	gardenLimits := garden.Limits{}
   121  	if cl.CPU == nil {
   122  		gardenLimits.CPU = garden.CPULimits{LimitInShares: GardenLimitDefault}
   123  	} else {
   124  		gardenLimits.CPU = garden.CPULimits{LimitInShares: *cl.CPU}
   125  	}
   126  	if cl.Memory == nil {
   127  		gardenLimits.Memory = garden.MemoryLimits{LimitInBytes: GardenLimitDefault}
   128  	} else {
   129  		gardenLimits.Memory = garden.MemoryLimits{LimitInBytes: *cl.Memory}
   130  	}
   131  	return gardenLimits
   132  }
   133  
   134  func (spec WorkerSpec) Description() string {
   135  	var attrs []string
   136  
   137  	if spec.ResourceType != "" {
   138  		attrs = append(attrs, fmt.Sprintf("resource type '%s'", spec.ResourceType))
   139  	}
   140  
   141  	if spec.Platform != "" {
   142  		attrs = append(attrs, fmt.Sprintf("platform '%s'", spec.Platform))
   143  	}
   144  
   145  	for _, tag := range spec.Tags {
   146  		attrs = append(attrs, fmt.Sprintf("tag '%s'", tag))
   147  	}
   148  
   149  	return strings.Join(attrs, ", ")
   150  }