forked from vmware-archive/atc
/
put_action.go
182 lines (157 loc) · 4.38 KB
/
put_action.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package exec
import (
"os"
"code.cloudfoundry.org/lager"
"github.com/concourse/atc"
"github.com/concourse/atc/creds"
"github.com/concourse/atc/db"
"github.com/concourse/atc/resource"
"github.com/concourse/atc/worker"
)
// PutAction produces a resource version using preconfigured params and any data
// available in the worker.ArtifactRepository.
type PutAction struct {
Type string
Name string
Resource string
Source creds.Source
Params atc.Params
Tags atc.Tags
imageFetchingDelegate ImageFetchingDelegate
resourceFactory resource.ResourceFactory
teamID int
buildID int
planID atc.PlanID
containerMetadata db.ContainerMetadata
stepMetadata StepMetadata
resourceTypes creds.VersionedResourceTypes
versionInfo VersionInfo
exitStatus ExitStatus
}
func NewPutAction(
resourceType string,
name string,
resourceName string,
source creds.Source,
params atc.Params,
tags atc.Tags,
imageFetchingDelegate ImageFetchingDelegate,
resourceFactory resource.ResourceFactory,
teamID int,
buildID int,
planID atc.PlanID,
containerMetadata db.ContainerMetadata,
stepMetadata StepMetadata,
resourceTypes creds.VersionedResourceTypes,
) *PutAction {
return &PutAction{
Type: resourceType,
Name: name,
Resource: resourceName,
Source: source,
Params: params,
Tags: tags,
imageFetchingDelegate: imageFetchingDelegate,
resourceFactory: resourceFactory,
teamID: teamID,
buildID: buildID,
planID: planID,
containerMetadata: containerMetadata,
stepMetadata: stepMetadata,
resourceTypes: resourceTypes,
}
}
// Run chooses a worker that supports the step's resource type and creates a
// container.
//
// All worker.ArtifactSources present in the worker.ArtifactRepository are then brought into
// the container, using volumes if possible, and streaming content over if not.
//
// The resource's put script is then invoked. The PutStep is ready as soon as
// the resource's script starts, and signals will be forwarded to the script.
func (action *PutAction) Run(
logger lager.Logger,
repository *worker.ArtifactRepository,
// TODO: consider passing these as context
signals <-chan os.Signal,
ready chan<- struct{},
) error {
containerSpec := worker.ContainerSpec{
ImageSpec: worker.ImageSpec{
ResourceType: action.Type,
},
Tags: action.Tags,
TeamID: action.teamID,
Dir: resource.ResourcesDir("put"),
Env: action.stepMetadata.Env(),
}
for name, source := range repository.AsMap() {
containerSpec.Inputs = append(containerSpec.Inputs, &putInputSource{
name: name,
source: PutResourceSource{source},
})
}
putResource, err := action.resourceFactory.NewResource(
logger,
signals,
db.ForBuild(action.buildID),
db.NewBuildStepContainerOwner(action.buildID, action.planID),
action.containerMetadata,
containerSpec,
action.resourceTypes,
action.imageFetchingDelegate,
)
if err != nil {
return err
}
source, err := action.Source.Evaluate()
if err != nil {
return err
}
versionedSource, err := putResource.Put(
resource.IOConfig{
Stdout: action.imageFetchingDelegate.Stdout(),
Stderr: action.imageFetchingDelegate.Stderr(),
},
source,
action.Params,
signals,
ready,
)
if err != nil {
if err, ok := err.(resource.ErrResourceScriptFailed); ok {
action.exitStatus = ExitStatus(err.ExitStatus)
return nil
}
return err
}
action.versionInfo = VersionInfo{
Version: versionedSource.Version(),
Metadata: versionedSource.Metadata(),
}
action.exitStatus = ExitStatus(0)
return nil
}
// VersionInfo returns the produced resource's version
// and metadata.
func (action *PutAction) VersionInfo() VersionInfo {
return action.versionInfo
}
// ExitStatus returns exit status of resource put script.
func (action *PutAction) ExitStatus() ExitStatus {
return action.exitStatus
}
type PutResourceSource struct {
worker.ArtifactSource
}
func (source PutResourceSource) StreamTo(dest worker.ArtifactDestination) error {
return source.ArtifactSource.StreamTo(worker.ArtifactDestination(dest))
}
type putInputSource struct {
name worker.ArtifactName
source worker.ArtifactSource
}
func (s *putInputSource) Source() worker.ArtifactSource { return s.source }
func (s *putInputSource) DestinationPath() string {
return resource.ResourcesDir("put/" + string(s.name))
}