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 }