github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/exec/get_step.go (about) 1 package exec 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 8 "code.cloudfoundry.org/lager" 9 "code.cloudfoundry.org/lager/lagerctx" 10 "github.com/pf-qiu/concourse/v6/atc" 11 "github.com/pf-qiu/concourse/v6/atc/creds" 12 "github.com/pf-qiu/concourse/v6/atc/db" 13 "github.com/pf-qiu/concourse/v6/atc/exec/build" 14 "github.com/pf-qiu/concourse/v6/atc/resource" 15 "github.com/pf-qiu/concourse/v6/atc/runtime" 16 "github.com/pf-qiu/concourse/v6/atc/worker" 17 "github.com/pf-qiu/concourse/v6/tracing" 18 "go.opentelemetry.io/otel/api/trace" 19 ) 20 21 type ErrPipelineNotFound struct { 22 PipelineName string 23 } 24 25 func (e ErrPipelineNotFound) Error() string { 26 return fmt.Sprintf("pipeline '%s' not found", e.PipelineName) 27 } 28 29 type ErrResourceNotFound struct { 30 ResourceName string 31 } 32 33 func (e ErrResourceNotFound) Error() string { 34 return fmt.Sprintf("resource '%s' not found", e.ResourceName) 35 } 36 37 //go:generate counterfeiter . GetDelegateFactory 38 39 type GetDelegateFactory interface { 40 GetDelegate(state RunState) GetDelegate 41 } 42 43 //go:generate counterfeiter . GetDelegate 44 45 type GetDelegate interface { 46 StartSpan(context.Context, string, tracing.Attrs) (context.Context, trace.Span) 47 48 FetchImage(context.Context, atc.ImageResource, atc.VersionedResourceTypes, bool) (worker.ImageSpec, error) 49 50 Stdout() io.Writer 51 Stderr() io.Writer 52 53 Initializing(lager.Logger) 54 Starting(lager.Logger) 55 Finished(lager.Logger, ExitStatus, runtime.VersionResult) 56 SelectedWorker(lager.Logger, string) 57 Errored(lager.Logger, string) 58 59 UpdateVersion(lager.Logger, atc.GetPlan, runtime.VersionResult) 60 } 61 62 // GetStep will fetch a version of a resource on a worker that supports the 63 // resource type. 64 type GetStep struct { 65 planID atc.PlanID 66 plan atc.GetPlan 67 metadata StepMetadata 68 containerMetadata db.ContainerMetadata 69 resourceFactory resource.ResourceFactory 70 resourceCacheFactory db.ResourceCacheFactory 71 strategy worker.ContainerPlacementStrategy 72 workerClient worker.Client 73 delegateFactory GetDelegateFactory 74 } 75 76 func NewGetStep( 77 planID atc.PlanID, 78 plan atc.GetPlan, 79 metadata StepMetadata, 80 containerMetadata db.ContainerMetadata, 81 resourceFactory resource.ResourceFactory, 82 resourceCacheFactory db.ResourceCacheFactory, 83 strategy worker.ContainerPlacementStrategy, 84 delegateFactory GetDelegateFactory, 85 client worker.Client, 86 ) Step { 87 return &GetStep{ 88 planID: planID, 89 plan: plan, 90 metadata: metadata, 91 containerMetadata: containerMetadata, 92 resourceFactory: resourceFactory, 93 resourceCacheFactory: resourceCacheFactory, 94 strategy: strategy, 95 delegateFactory: delegateFactory, 96 workerClient: client, 97 } 98 } 99 100 func (step *GetStep) Run(ctx context.Context, state RunState) (bool, error) { 101 delegate := step.delegateFactory.GetDelegate(state) 102 ctx, span := delegate.StartSpan(ctx, "get", tracing.Attrs{ 103 "name": step.plan.Name, 104 "resource": step.plan.Resource, 105 }) 106 107 ok, err := step.run(ctx, state, delegate) 108 tracing.End(span, err) 109 110 return ok, err 111 } 112 113 func (step *GetStep) run(ctx context.Context, state RunState, delegate GetDelegate) (bool, error) { 114 logger := lagerctx.FromContext(ctx) 115 logger = logger.Session("get-step", lager.Data{ 116 "step-name": step.plan.Name, 117 }) 118 119 delegate.Initializing(logger) 120 121 source, err := creds.NewSource(state, step.plan.Source).Evaluate() 122 if err != nil { 123 return false, err 124 } 125 126 params, err := creds.NewParams(state, step.plan.Params).Evaluate() 127 if err != nil { 128 return false, err 129 } 130 131 workerSpec := worker.WorkerSpec{ 132 Tags: step.plan.Tags, 133 TeamID: step.metadata.TeamID, 134 ResourceType: step.plan.VersionedResourceTypes.Base(step.plan.Type), 135 } 136 137 var imageSpec worker.ImageSpec 138 resourceType, found := step.plan.VersionedResourceTypes.Lookup(step.plan.Type) 139 if found { 140 image := atc.ImageResource{ 141 Name: resourceType.Name, 142 Type: resourceType.Type, 143 Source: resourceType.Source, 144 Params: resourceType.Params, 145 Version: resourceType.Version, 146 Tags: resourceType.Tags, 147 } 148 if len(image.Tags) == 0 { 149 image.Tags = step.plan.Tags 150 } 151 152 types := step.plan.VersionedResourceTypes.Without(step.plan.Type) 153 154 var err error 155 imageSpec, err = delegate.FetchImage(ctx, image, types, resourceType.Privileged) 156 if err != nil { 157 return false, err 158 } 159 } else { 160 imageSpec.ResourceType = step.plan.Type 161 } 162 163 resourceTypes, err := creds.NewVersionedResourceTypes(state, step.plan.VersionedResourceTypes).Evaluate() 164 if err != nil { 165 return false, err 166 } 167 168 version, err := NewVersionSourceFromPlan(&step.plan).Version(state) 169 if err != nil { 170 return false, err 171 } 172 173 containerSpec := worker.ContainerSpec{ 174 ImageSpec: imageSpec, 175 TeamID: step.metadata.TeamID, 176 Env: step.metadata.Env(), 177 } 178 tracing.Inject(ctx, &containerSpec) 179 180 resourceCache, err := step.resourceCacheFactory.FindOrCreateResourceCache( 181 db.ForBuild(step.metadata.BuildID), 182 step.plan.Type, 183 version, 184 source, 185 params, 186 resourceTypes, 187 ) 188 if err != nil { 189 logger.Error("failed-to-create-resource-cache", err) 190 return false, err 191 } 192 193 processSpec := runtime.ProcessSpec{ 194 Path: "/opt/resource/in", 195 Args: []string{resource.ResourcesDir("get")}, 196 StdoutWriter: delegate.Stdout(), 197 StderrWriter: delegate.Stderr(), 198 } 199 200 resourceToGet := step.resourceFactory.NewResource( 201 source, 202 params, 203 version, 204 ) 205 206 containerOwner := db.NewBuildStepContainerOwner(step.metadata.BuildID, step.planID, step.metadata.TeamID) 207 208 getResult, err := step.workerClient.RunGetStep( 209 ctx, 210 logger, 211 containerOwner, 212 containerSpec, 213 workerSpec, 214 step.strategy, 215 step.containerMetadata, 216 processSpec, 217 delegate, 218 resourceCache, 219 resourceToGet, 220 ) 221 if err != nil { 222 return false, err 223 } 224 225 var succeeded bool 226 if getResult.ExitStatus == 0 { 227 state.StoreResult(step.planID, resourceCache) 228 229 state.ArtifactRepository().RegisterArtifact( 230 build.ArtifactName(step.plan.Name), 231 getResult.GetArtifact, 232 ) 233 234 if step.plan.Resource != "" { 235 delegate.UpdateVersion(logger, step.plan, getResult.VersionResult) 236 } 237 238 succeeded = true 239 } 240 241 delegate.Finished( 242 logger, 243 ExitStatus(getResult.ExitStatus), 244 getResult.VersionResult, 245 ) 246 247 return succeeded, nil 248 }