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  }