Upstream concourse/concourse state of the touched files before bb8b7aa7e9
This commit is contained in:
commit
af4510fc7f
4 files changed
+2739
No files matched your search
@@ -0,0 +1,284 @@
|
||||
package exec
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"code.cloudfoundry.org/lager/v3"
|
||||
"code.cloudfoundry.org/lager/v3/lagerctx"
|
||||
"github.com/concourse/concourse/atc"
|
||||
"github.com/concourse/concourse/atc/exec/build"
|
||||
"github.com/concourse/concourse/vars"
|
||||
"github.com/concourse/concourse/worker/baggageclaim"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
//counterfeiter:generate . TaskConfigSource
|
||||
|
||||
// TaskConfigSource is used to determine a Task step's TaskConfig.
|
||||
type TaskConfigSource interface {
|
||||
// FetchConfig returns the TaskConfig, and may have to a task config file out
|
||||
// of the artifact.Repository.
|
||||
FetchConfig(context.Context, lager.Logger, *build.Repository) (atc.TaskConfig, error)
|
||||
Warnings() []string
|
||||
}
|
||||
|
||||
// StaticConfigSource represents a statically configured TaskConfig.
|
||||
type StaticConfigSource struct {
|
||||
Config *atc.TaskConfig
|
||||
}
|
||||
|
||||
// FetchConfig returns the configuration.
|
||||
func (configSource StaticConfigSource) FetchConfig(context.Context, lager.Logger, *build.Repository) (atc.TaskConfig, error) {
|
||||
taskConfig := atc.TaskConfig{}
|
||||
if configSource.Config != nil {
|
||||
taskConfig = *configSource.Config
|
||||
}
|
||||
return taskConfig, nil
|
||||
}
|
||||
|
||||
func (configSource StaticConfigSource) Warnings() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// FileConfigSource represents a dynamically configured TaskConfig, which will
|
||||
// be fetched from a specified file in the artifact.Repository.
|
||||
type FileConfigSource struct {
|
||||
ConfigPath string
|
||||
Streamer Streamer
|
||||
}
|
||||
|
||||
// FetchConfig reads the specified file from the artifact.Repository and loads the
|
||||
// TaskConfig contained therein (expecting it to be YAML format).
|
||||
//
|
||||
// The path must be in the format SOURCE_NAME/FILE/PATH.yml. The SOURCE_NAME
|
||||
// will be used to determine the StreamableArtifactSource in the artifact.Repository to
|
||||
// stream the file out of.
|
||||
//
|
||||
// If the source name is missing (i.e. if the path is just "foo.yml"),
|
||||
// UnspecifiedArtifactSourceError is returned.
|
||||
//
|
||||
// If the specified source name cannot be found, UnknownArtifactSourceError is
|
||||
// returned.
|
||||
//
|
||||
// If the task config file is not found, or is invalid YAML, or is an invalid
|
||||
// task configuration, the respective errors will be bubbled up.
|
||||
func (configSource FileConfigSource) FetchConfig(ctx context.Context, logger lager.Logger, repo *build.Repository) (atc.TaskConfig, error) {
|
||||
segs := strings.SplitN(configSource.ConfigPath, "/", 2)
|
||||
if len(segs) != 2 {
|
||||
return atc.TaskConfig{}, UnspecifiedArtifactSourceError{configSource.ConfigPath}
|
||||
}
|
||||
|
||||
sourceName := build.ArtifactName(segs[0])
|
||||
filePath := segs[1]
|
||||
|
||||
artifact, _, found := repo.ArtifactFor(sourceName)
|
||||
if !found {
|
||||
return atc.TaskConfig{}, UnknownArtifactSourceError{sourceName, configSource.ConfigPath}
|
||||
}
|
||||
stream, err := configSource.Streamer.StreamFile(lagerctx.NewContext(ctx, logger), artifact, filePath)
|
||||
if err != nil {
|
||||
if err == baggageclaim.ErrFileNotFound {
|
||||
return atc.TaskConfig{}, fmt.Errorf("task config '%s/%s' not found", sourceName, filePath)
|
||||
}
|
||||
return atc.TaskConfig{}, err
|
||||
}
|
||||
|
||||
defer stream.Close()
|
||||
|
||||
byteConfig, err := io.ReadAll(stream)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, err
|
||||
}
|
||||
|
||||
config, err := atc.NewTaskConfig(byteConfig)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, fmt.Errorf("failed to create task config from bytes %s: %s", configSource.ConfigPath, err)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (configSource FileConfigSource) Warnings() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// BaseResourceTypeDefaultsApplySource applies base resource type defaults to image_source.
|
||||
type BaseResourceTypeDefaultsApplySource struct {
|
||||
ConfigSource TaskConfigSource
|
||||
ResourceTypes atc.ResourceTypes
|
||||
}
|
||||
|
||||
func (configSource BaseResourceTypeDefaultsApplySource) FetchConfig(ctx context.Context, logger lager.Logger, repo *build.Repository) (atc.TaskConfig, error) {
|
||||
config, err := configSource.ConfigSource.FetchConfig(ctx, logger, repo)
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
|
||||
config.ImageResource.ApplySourceDefaults(configSource.ResourceTypes)
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (configSource BaseResourceTypeDefaultsApplySource) Warnings() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
type OverrideContainerLimitsSource struct {
|
||||
ConfigSource TaskConfigSource
|
||||
Limits *atc.ContainerLimits
|
||||
}
|
||||
|
||||
// FetchConfig overrides container limits, allowing the user to set container limits required by a task loaded
|
||||
// from a file by providing them in static configuration.
|
||||
func (configSource *OverrideContainerLimitsSource) FetchConfig(ctx context.Context, logger lager.Logger, source *build.Repository) (atc.TaskConfig, error) {
|
||||
taskConfig, err := configSource.ConfigSource.FetchConfig(ctx, logger, source)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, err
|
||||
}
|
||||
|
||||
if configSource.Limits == nil {
|
||||
return taskConfig, nil
|
||||
}
|
||||
|
||||
if taskConfig.Limits == nil {
|
||||
taskConfig.Limits = &atc.ContainerLimits{}
|
||||
}
|
||||
|
||||
if configSource.Limits.CPU != nil {
|
||||
taskConfig.Limits.CPU = configSource.Limits.CPU
|
||||
}
|
||||
|
||||
if configSource.Limits.Memory != nil {
|
||||
taskConfig.Limits.Memory = configSource.Limits.Memory
|
||||
}
|
||||
|
||||
return taskConfig, nil
|
||||
}
|
||||
|
||||
func (configSource *OverrideContainerLimitsSource) Warnings() []string {
|
||||
return make([]string, 0)
|
||||
}
|
||||
|
||||
var _ TaskConfigSource = &OverrideContainerLimitsSource{}
|
||||
|
||||
// OverrideParamsConfigSource is used to override params in a config source
|
||||
type OverrideParamsConfigSource struct {
|
||||
ConfigSource TaskConfigSource
|
||||
Params atc.TaskEnv
|
||||
WarningList []string
|
||||
}
|
||||
|
||||
// FetchConfig overrides parameters, allowing the user to set params required by a task loaded
|
||||
// from a file by providing them in static configuration.
|
||||
func (configSource *OverrideParamsConfigSource) FetchConfig(ctx context.Context, logger lager.Logger, source *build.Repository) (atc.TaskConfig, error) {
|
||||
taskConfig, err := configSource.ConfigSource.FetchConfig(ctx, logger, source)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, err
|
||||
}
|
||||
|
||||
if taskConfig.Params == nil {
|
||||
taskConfig.Params = atc.TaskEnv{}
|
||||
}
|
||||
|
||||
for key, val := range configSource.Params {
|
||||
if _, exists := taskConfig.Params[key]; !exists {
|
||||
configSource.WarningList = append(configSource.WarningList, fmt.Sprintf("%s was defined in pipeline but missing from task file", key))
|
||||
}
|
||||
|
||||
taskConfig.Params[key] = val
|
||||
}
|
||||
|
||||
return taskConfig, nil
|
||||
}
|
||||
|
||||
func (configSource OverrideParamsConfigSource) Warnings() []string {
|
||||
return configSource.WarningList
|
||||
}
|
||||
|
||||
// InterpolateTemplateConfigSource represents a config source interpolated by template vars
|
||||
type InterpolateTemplateConfigSource struct {
|
||||
ConfigSource TaskConfigSource
|
||||
Vars []vars.Variables
|
||||
ExpectAllKeys bool
|
||||
}
|
||||
|
||||
// FetchConfig returns the interpolated configuration
|
||||
func (configSource InterpolateTemplateConfigSource) FetchConfig(ctx context.Context, logger lager.Logger, source *build.Repository) (atc.TaskConfig, error) {
|
||||
taskConfig, err := configSource.ConfigSource.FetchConfig(ctx, logger, source)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, err
|
||||
}
|
||||
|
||||
byteConfig, err := yaml.Marshal(taskConfig)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, fmt.Errorf("failed to marshal task config: %s", err)
|
||||
}
|
||||
|
||||
// process task config using the provided variables
|
||||
byteConfig, err = vars.NewTemplateResolver(byteConfig, configSource.Vars).Resolve(configSource.ExpectAllKeys)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, fmt.Errorf("failed to interpolate task config: %s", err)
|
||||
}
|
||||
|
||||
taskConfig, err = atc.NewTaskConfig(byteConfig)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, fmt.Errorf("failed to create task config from bytes: %s", err)
|
||||
}
|
||||
|
||||
return taskConfig, nil
|
||||
}
|
||||
|
||||
func (configSource InterpolateTemplateConfigSource) Warnings() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// ValidatingConfigSource delegates to another ConfigSource, and validates its
|
||||
// task config.
|
||||
type ValidatingConfigSource struct {
|
||||
ConfigSource TaskConfigSource
|
||||
}
|
||||
|
||||
// FetchConfig fetches the config using the underlying ConfigSource, and checks
|
||||
// that it's valid.
|
||||
func (configSource ValidatingConfigSource) FetchConfig(ctx context.Context, logger lager.Logger, source *build.Repository) (atc.TaskConfig, error) {
|
||||
config, err := configSource.ConfigSource.FetchConfig(ctx, logger, source)
|
||||
if err != nil {
|
||||
return atc.TaskConfig{}, err
|
||||
}
|
||||
|
||||
if err := config.Validate(); err != nil {
|
||||
return atc.TaskConfig{}, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (configSource ValidatingConfigSource) Warnings() []string {
|
||||
return configSource.ConfigSource.Warnings()
|
||||
}
|
||||
|
||||
// UnknownArtifactSourceError is returned when the artifact.ArtifactName specified by the
|
||||
// path does not exist in the artifact.Repository.
|
||||
type UnknownArtifactSourceError struct {
|
||||
SourceName build.ArtifactName
|
||||
ConfigPath string
|
||||
}
|
||||
|
||||
// Error returns a human-friendly error message.
|
||||
func (err UnknownArtifactSourceError) Error() string {
|
||||
return fmt.Sprintf("unknown artifact source: '%s' in file path '%s'", err.SourceName, err.ConfigPath)
|
||||
}
|
||||
|
||||
// UnspecifiedArtifactSourceError is returned when the specified path is of a
|
||||
// file in the toplevel directory, and so it does not indicate a SourceName.
|
||||
type UnspecifiedArtifactSourceError struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Error returns a human-friendly error message.
|
||||
func (err UnspecifiedArtifactSourceError) Error() string {
|
||||
return fmt.Sprintf("config path '%s' does not specify where the file lives", err.Path)
|
||||
}
|
||||
Reference in new issue
Block a user