github.com/chenbh/concourse/v6@v6.4.2/fly/commands/internal/executehelpers/inputs.go (about) 1 package executehelpers 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path/filepath" 8 "sync" 9 10 "github.com/chenbh/concourse/v6/atc" 11 "github.com/chenbh/concourse/v6/fly/commands/internal/flaghelpers" 12 "github.com/chenbh/concourse/v6/fly/ui/progress" 13 "github.com/chenbh/concourse/v6/go-concourse/concourse" 14 "github.com/vbauerster/mpb/v4" 15 ) 16 17 type Input struct { 18 Name string 19 Path string 20 21 Plan atc.Plan 22 } 23 24 func DetermineInputs( 25 fact atc.PlanFactory, 26 team concourse.Team, 27 taskInputs []atc.TaskInputConfig, 28 localInputMappings []flaghelpers.InputPairFlag, 29 userInputMappings []flaghelpers.VariablePairFlag, 30 jobInputImage string, 31 inputsFrom flaghelpers.JobFlag, 32 includeIgnored bool, 33 platform string, 34 ) ([]Input, map[string]string, *atc.ImageResource, atc.VersionedResourceTypes, error) { 35 inputMappings := ConvertInputMappings(userInputMappings) 36 37 err := CheckForUnknownInputMappings(localInputMappings, taskInputs) 38 if err != nil { 39 return nil, nil, nil, nil, err 40 } 41 42 err = CheckForInputType(localInputMappings) 43 if err != nil { 44 return nil, nil, nil, nil, err 45 } 46 47 if len(localInputMappings) == 0 && inputsFrom.PipelineName == "" && inputsFrom.JobName == "" { 48 wd, err := os.Getwd() 49 if err != nil { 50 return nil, nil, nil, nil, err 51 } 52 53 localInputMappings = append(localInputMappings, flaghelpers.InputPairFlag{ 54 Name: filepath.Base(wd), 55 Path: ".", 56 }) 57 } 58 59 inputsFromLocal, err := GenerateLocalInputs(fact, team, localInputMappings, includeIgnored, platform) 60 if err != nil { 61 return nil, nil, nil, nil, err 62 } 63 64 inputsFromJob, imageResourceFromJob, resourceTypes, err := FetchInputsFromJob(fact, team, inputsFrom, jobInputImage) 65 if err != nil { 66 return nil, nil, nil, nil, err 67 } 68 69 inputs := []Input{} 70 for _, taskInput := range taskInputs { 71 input, found := inputsFromLocal[taskInput.Name] 72 if !found { 73 74 jobInputName := taskInput.Name 75 if name, ok := inputMappings[taskInput.Name]; ok { 76 jobInputName = name 77 } 78 79 input, found = inputsFromJob[jobInputName] 80 if !found { 81 if taskInput.Optional { 82 continue 83 } else { 84 return nil, nil, nil, nil, fmt.Errorf("missing required input `%s`", taskInput.Name) 85 } 86 } 87 } 88 89 inputs = append(inputs, input) 90 } 91 92 return inputs, inputMappings, imageResourceFromJob, resourceTypes, nil 93 } 94 95 func ConvertInputMappings(variables []flaghelpers.VariablePairFlag) map[string]string { 96 inputMappings := map[string]string{} 97 for _, flag := range variables { 98 inputMappings[flag.Name] = flag.Value 99 } 100 return inputMappings 101 } 102 103 func CheckForInputType(inputMaps []flaghelpers.InputPairFlag) error { 104 for _, i := range inputMaps { 105 if i.Path != "" { 106 fi, err := os.Stat(i.Path) 107 if err != nil { 108 return err 109 } 110 switch mode := fi.Mode(); { 111 case mode.IsRegular(): 112 return errors.New(i.Path + " not a folder") 113 } 114 } 115 } 116 return nil 117 } 118 119 func CheckForUnknownInputMappings(inputMappings []flaghelpers.InputPairFlag, validInputs []atc.TaskInputConfig) error { 120 for _, inputMapping := range inputMappings { 121 if !TaskInputsContainsName(validInputs, inputMapping.Name) { 122 return fmt.Errorf("unknown input `%s`", inputMapping.Name) 123 } 124 } 125 return nil 126 } 127 128 func TaskInputsContainsName(inputs []atc.TaskInputConfig, name string) bool { 129 for _, input := range inputs { 130 if input.Name == name { 131 return true 132 } 133 } 134 return false 135 } 136 137 func GenerateLocalInputs( 138 fact atc.PlanFactory, 139 team concourse.Team, 140 inputMappings []flaghelpers.InputPairFlag, 141 includeIgnored bool, 142 platform string, 143 ) (map[string]Input, error) { 144 inputs := map[string]Input{} 145 146 artifacts := new(sync.Map) 147 148 prog := progress.New() 149 150 for _, mapping := range inputMappings { 151 name := mapping.Name 152 path := mapping.Path 153 154 prog.Go("uploading "+name, func(bar *mpb.Bar) error { 155 artifact, err := Upload(bar, team, path, includeIgnored, platform) 156 if err != nil { 157 return err 158 } 159 160 artifacts.Store(name, artifact) 161 162 return nil 163 }) 164 } 165 166 err := prog.Wait() 167 if err != nil { 168 return nil, err 169 } 170 171 for _, mapping := range inputMappings { 172 val, _ := artifacts.Load(mapping.Name) 173 174 inputs[mapping.Name] = Input{ 175 Name: mapping.Name, 176 Path: mapping.Path, 177 Plan: fact.NewPlan(atc.ArtifactInputPlan{ 178 ArtifactID: val.(atc.WorkerArtifact).ID, 179 Name: mapping.Name, 180 }), 181 } 182 } 183 184 return inputs, nil 185 } 186 187 func FetchInputsFromJob(fact atc.PlanFactory, team concourse.Team, inputsFrom flaghelpers.JobFlag, imageName string) (map[string]Input, *atc.ImageResource, atc.VersionedResourceTypes, error) { 188 kvMap := map[string]Input{} 189 190 if inputsFrom.PipelineName == "" && inputsFrom.JobName == "" { 191 return kvMap, nil, nil, nil 192 } 193 194 buildInputs, found, err := team.BuildInputsForJob(inputsFrom.PipelineName, inputsFrom.JobName) 195 if err != nil { 196 return nil, nil, nil, err 197 } 198 199 if !found { 200 return nil, nil, nil, fmt.Errorf("build inputs for %s/%s not found", inputsFrom.PipelineName, inputsFrom.JobName) 201 } 202 203 versionedResourceTypes, found, err := team.VersionedResourceTypes(inputsFrom.PipelineName) 204 if err != nil { 205 return nil, nil, nil, err 206 } 207 208 if !found { 209 return nil, nil, nil, fmt.Errorf("versioned resource types of %s not found", inputsFrom.PipelineName) 210 } 211 212 var imageResource *atc.ImageResource 213 if imageName != "" { 214 imageResource, found, err = FetchImageResourceFromJobInputs(buildInputs, imageName) 215 if err != nil { 216 return nil, nil, nil, err 217 } 218 219 if !found { 220 return nil, nil, nil, fmt.Errorf("image resource %s not found", imageName) 221 } 222 } 223 224 for _, buildInput := range buildInputs { 225 version := buildInput.Version 226 227 kvMap[buildInput.Name] = Input{ 228 Name: buildInput.Name, 229 230 Plan: fact.NewPlan(atc.GetPlan{ 231 Name: buildInput.Name, 232 Type: buildInput.Type, 233 Source: buildInput.Source, 234 Version: &version, 235 Params: buildInput.Params, 236 Tags: buildInput.Tags, 237 VersionedResourceTypes: versionedResourceTypes, 238 }), 239 } 240 } 241 242 return kvMap, imageResource, versionedResourceTypes, nil 243 } 244 245 func FetchImageResourceFromJobInputs(inputs []atc.BuildInput, imageName string) (*atc.ImageResource, bool, error) { 246 247 for _, input := range inputs { 248 if input.Name == imageName { 249 version := input.Version 250 imageResource := atc.ImageResource{ 251 Type: input.Type, 252 Source: input.Source, 253 Version: version, 254 Params: input.Params, 255 } 256 return &imageResource, true, nil 257 } 258 } 259 260 return nil, false, nil 261 }