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

     1  package image
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net/url"
     7  	"path"
     8  
     9  	"code.cloudfoundry.org/lager"
    10  	"github.com/concourse/baggageclaim"
    11  	"github.com/pf-qiu/concourse/v6/atc"
    12  	"github.com/pf-qiu/concourse/v6/atc/db"
    13  	"github.com/pf-qiu/concourse/v6/atc/worker"
    14  	"github.com/pf-qiu/concourse/v6/tracing"
    15  )
    16  
    17  const RawRootFSScheme = "raw"
    18  
    19  const ImageMetadataFile = "metadata.json"
    20  
    21  type imageProvidedByPreviousStepOnSameWorker struct {
    22  	artifactVolume worker.Volume
    23  	imageSpec      worker.ImageSpec
    24  	teamID         int
    25  	volumeClient   worker.VolumeClient
    26  }
    27  
    28  func (i *imageProvidedByPreviousStepOnSameWorker) FetchForContainer(
    29  	ctx context.Context,
    30  	logger lager.Logger,
    31  	container db.CreatingContainer,
    32  ) (worker.FetchedImage, error) {
    33  	imageVolume, err := i.volumeClient.FindOrCreateCOWVolumeForContainer(
    34  		logger,
    35  		worker.VolumeSpec{
    36  			Strategy:   i.artifactVolume.COWStrategy(),
    37  			Privileged: i.imageSpec.Privileged,
    38  		},
    39  		container,
    40  		i.artifactVolume,
    41  		i.teamID,
    42  		"/",
    43  	)
    44  	if err != nil {
    45  		logger.Error("failed-to-create-image-artifact-cow-volume", err)
    46  		return worker.FetchedImage{}, err
    47  	}
    48  
    49  	imageMetadataReader, err := i.imageSpec.ImageArtifactSource.StreamFile(ctx, ImageMetadataFile)
    50  	if err != nil {
    51  		logger.Error("failed-to-stream-metadata-file", err)
    52  		return worker.FetchedImage{}, err
    53  	}
    54  
    55  	metadata, err := loadMetadata(imageMetadataReader)
    56  	if err != nil {
    57  		return worker.FetchedImage{}, err
    58  	}
    59  
    60  	imageURL := url.URL{
    61  		Scheme: RawRootFSScheme,
    62  		Path:   path.Join(imageVolume.Path(), "rootfs"),
    63  	}
    64  
    65  	return worker.FetchedImage{
    66  		Metadata:   metadata,
    67  		URL:        imageURL.String(),
    68  		Privileged: i.imageSpec.Privileged,
    69  	}, nil
    70  }
    71  
    72  type imageProvidedByPreviousStepOnDifferentWorker struct {
    73  	imageSpec    worker.ImageSpec
    74  	teamID       int
    75  	volumeClient worker.VolumeClient
    76  }
    77  
    78  func (i *imageProvidedByPreviousStepOnDifferentWorker) FetchForContainer(
    79  	ctx context.Context,
    80  	logger lager.Logger,
    81  	container db.CreatingContainer,
    82  ) (worker.FetchedImage, error) {
    83  	ctx, span := tracing.StartSpan(ctx, "imageProvidedByPreviousStepOnDifferentWorker.FetchForContainer", tracing.Attrs{"container_id": container.Handle()})
    84  	defer span.End()
    85  
    86  	imageVolume, err := i.volumeClient.FindOrCreateVolumeForContainer(
    87  		logger,
    88  		worker.VolumeSpec{
    89  			Strategy:   baggageclaim.EmptyStrategy{},
    90  			Privileged: i.imageSpec.Privileged,
    91  		},
    92  		container,
    93  		i.teamID,
    94  		"/",
    95  	)
    96  	if err != nil {
    97  		logger.Error("failed-to-create-image-artifact-replicated-volume", err)
    98  		return worker.FetchedImage{}, err
    99  	}
   100  
   101  	dest := artifactDestination{
   102  		destination: imageVolume,
   103  	}
   104  
   105  	err = i.imageSpec.ImageArtifactSource.StreamTo(ctx, &dest)
   106  	if err != nil {
   107  		logger.Error("failed-to-stream-image-artifact-source", err)
   108  		return worker.FetchedImage{}, err
   109  	}
   110  	logger.Debug("streamed-non-local-image-volume")
   111  
   112  	imageMetadataReader, err := i.imageSpec.ImageArtifactSource.StreamFile(ctx, ImageMetadataFile)
   113  	if err != nil {
   114  		logger.Error("failed-to-stream-metadata-file", err)
   115  		return worker.FetchedImage{}, err
   116  	}
   117  
   118  	metadata, err := loadMetadata(imageMetadataReader)
   119  	if err != nil {
   120  		return worker.FetchedImage{}, err
   121  	}
   122  
   123  	imageURL := url.URL{
   124  		Scheme: RawRootFSScheme,
   125  		Path:   path.Join(imageVolume.Path(), "rootfs"),
   126  	}
   127  
   128  	return worker.FetchedImage{
   129  		Metadata:   metadata,
   130  		URL:        imageURL.String(),
   131  		Privileged: i.imageSpec.Privileged,
   132  	}, nil
   133  }
   134  
   135  type imageFromBaseResourceType struct {
   136  	worker           worker.Worker
   137  	resourceTypeName string
   138  	teamID           int
   139  	volumeClient     worker.VolumeClient
   140  }
   141  
   142  func (i *imageFromBaseResourceType) FetchForContainer(
   143  	ctx context.Context,
   144  	logger lager.Logger,
   145  	container db.CreatingContainer,
   146  ) (worker.FetchedImage, error) {
   147  	for _, t := range i.worker.ResourceTypes() {
   148  		if t.Type == i.resourceTypeName {
   149  			importVolume, err := i.volumeClient.FindOrCreateVolumeForBaseResourceType(
   150  				logger,
   151  				worker.VolumeSpec{
   152  					Strategy:   baggageclaim.ImportStrategy{Path: t.Image},
   153  					Privileged: t.Privileged,
   154  				},
   155  				i.teamID,
   156  				i.resourceTypeName,
   157  			)
   158  			if err != nil {
   159  				return worker.FetchedImage{}, err
   160  			}
   161  
   162  			cowVolume, err := i.volumeClient.FindOrCreateCOWVolumeForContainer(
   163  				logger,
   164  				worker.VolumeSpec{
   165  					Strategy:   importVolume.COWStrategy(),
   166  					Privileged: t.Privileged,
   167  				},
   168  				container,
   169  				importVolume,
   170  				i.teamID,
   171  				"/",
   172  			)
   173  			if err != nil {
   174  				return worker.FetchedImage{}, err
   175  			}
   176  
   177  			rootFSURL := url.URL{
   178  				Scheme: RawRootFSScheme,
   179  				Path:   cowVolume.Path(),
   180  			}
   181  
   182  			return worker.FetchedImage{
   183  				Metadata:   worker.ImageMetadata{},
   184  				Version:    atc.Version{i.resourceTypeName: t.Version},
   185  				URL:        rootFSURL.String(),
   186  				Privileged: t.Privileged,
   187  			}, nil
   188  		}
   189  	}
   190  
   191  	return worker.FetchedImage{}, ErrUnsupportedResourceType
   192  }
   193  
   194  type imageFromRootfsURI struct {
   195  	url string
   196  }
   197  
   198  func (i *imageFromRootfsURI) FetchForContainer(
   199  	ctx context.Context,
   200  	logger lager.Logger,
   201  	container db.CreatingContainer,
   202  ) (worker.FetchedImage, error) {
   203  	return worker.FetchedImage{
   204  		URL: i.url,
   205  	}, nil
   206  }
   207  
   208  type artifactDestination struct {
   209  	destination worker.Volume
   210  }
   211  
   212  func (wad *artifactDestination) StreamIn(ctx context.Context, path string, encoding baggageclaim.Encoding, tarStream io.Reader) error {
   213  	return wad.destination.StreamIn(ctx, path, encoding, tarStream)
   214  }
   215  
   216  func (wad *artifactDestination) GetStreamInP2pUrl(ctx context.Context, path string) (string, error) {
   217  	return wad.destination.GetStreamInP2pUrl(ctx, path)
   218  }