github.com/openshift/source-to-image@v1.4.1-0.20240516041539-bf52fc02204e/pkg/api/types.go (about)

     1  package api
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net/url"
     7  	"path/filepath"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/openshift/source-to-image/pkg/scm/git"
    12  	utillog "github.com/openshift/source-to-image/pkg/util/log"
    13  	"github.com/openshift/source-to-image/pkg/util/user"
    14  )
    15  
    16  var log = utillog.StderrLog
    17  
    18  // invalidFilenameCharacters contains a list of character we consider malicious
    19  // when injecting the directories into containers.
    20  const invalidFilenameCharacters = `;*?"<>|%#$!+{}&[],"'` + "`"
    21  
    22  const (
    23  	// PullAlways means that we always attempt to pull the latest image.
    24  	PullAlways PullPolicy = "always"
    25  
    26  	// PullNever means that we never pull an image, but only use a local image.
    27  	PullNever PullPolicy = "never"
    28  
    29  	// PullIfNotPresent means that we pull if the image isn't present on disk.
    30  	PullIfNotPresent PullPolicy = "if-not-present"
    31  
    32  	// DefaultBuilderPullPolicy specifies the default pull policy to use
    33  	DefaultBuilderPullPolicy = PullIfNotPresent
    34  
    35  	// DefaultRuntimeImagePullPolicy specifies the default pull policy to use.
    36  	DefaultRuntimeImagePullPolicy = PullIfNotPresent
    37  
    38  	// DefaultPreviousImagePullPolicy specifies policy for pulling the previously
    39  	// build Docker image when doing incremental build
    40  	DefaultPreviousImagePullPolicy = PullIfNotPresent
    41  )
    42  
    43  // Config contains essential fields for performing build.
    44  type Config struct {
    45  	// DisplayName is a result image display-name label. This defaults to the
    46  	// output image name.
    47  	DisplayName string
    48  
    49  	// Description is a result image description label. The default is no
    50  	// description.
    51  	Description string
    52  
    53  	// BuilderImage describes which image is used for building the result images.
    54  	BuilderImage string
    55  
    56  	// BuilderImageVersion provides optional version information about the builder image.
    57  	BuilderImageVersion string
    58  
    59  	// BuilderBaseImageVersion provides optional version information about the builder base image.
    60  	BuilderBaseImageVersion string
    61  
    62  	// RuntimeImage specifies the image that will be a base for resulting image
    63  	// and will be used for running an application. By default, BuilderImage is
    64  	// used for building and running, but the latter may be overridden.
    65  	RuntimeImage string
    66  
    67  	// RuntimeImagePullPolicy specifies when to pull a runtime image.
    68  	RuntimeImagePullPolicy PullPolicy
    69  
    70  	// RuntimeAuthentication holds the authentication information for pulling the
    71  	// runtime Docker images from private repositories.
    72  	RuntimeAuthentication AuthConfig
    73  
    74  	// RuntimeArtifacts specifies a list of source/destination pairs that will
    75  	// be copied from builder to a runtime image. Source can be a file or
    76  	// directory. Destination must be a directory. Regardless whether it
    77  	// is an absolute or relative path, it will be placed into image's WORKDIR.
    78  	// Destination also can be empty or equals to ".", in this case it just
    79  	// refers to a root of WORKDIR.
    80  	// In case it's empty, S2I will try to get this list from
    81  	// io.openshift.s2i.assemble-input-files label on a RuntimeImage.
    82  	RuntimeArtifacts VolumeList
    83  
    84  	// DockerConfig describes how to access host docker daemon.
    85  	DockerConfig *DockerConfig
    86  
    87  	// DockerCfgPath provides the path to the .dockercfg file
    88  	DockerCfgPath string
    89  
    90  	// PullAuthentication holds the authentication information for pulling the
    91  	// Docker images from private repositories
    92  	PullAuthentication AuthConfig
    93  
    94  	// IncrementalAuthentication holds the authentication information for pulling the
    95  	// previous image from private repositories
    96  	IncrementalAuthentication AuthConfig
    97  
    98  	// DockerNetworkMode is used to set the docker network setting to --net=container:<id>
    99  	// when the builder is invoked from a container.
   100  	DockerNetworkMode DockerNetworkMode
   101  
   102  	// PreserveWorkingDir describes if working directory should be left after processing.
   103  	PreserveWorkingDir bool
   104  
   105  	// IgnoreSubmodules determines whether we will attempt to pull in submodules
   106  	// (via --recursive or submodule init)
   107  	IgnoreSubmodules bool
   108  
   109  	// Source URL describing the location of sources used to build the result image.
   110  	Source *git.URL
   111  
   112  	// Tag is a result image tag name.
   113  	Tag string
   114  
   115  	// BuilderPullPolicy specifies when to pull the builder image
   116  	BuilderPullPolicy PullPolicy
   117  
   118  	// PreviousImagePullPolicy specifies when to pull the previously build image
   119  	// when doing incremental build
   120  	PreviousImagePullPolicy PullPolicy
   121  
   122  	// Incremental describes whether to try to perform incremental build.
   123  	Incremental bool
   124  
   125  	// IncrementalFromTag sets an alternative image tag to look for existing
   126  	// artifacts. Tag is used by default if this is not set.
   127  	IncrementalFromTag string
   128  
   129  	// RemovePreviousImage describes if previous image should be removed after successful build.
   130  	// This applies only to incremental builds.
   131  	RemovePreviousImage bool
   132  
   133  	// Environment is a map of environment variables to be passed to the image.
   134  	Environment EnvironmentList
   135  
   136  	// EnvironmentFile provides the path to a file with list of environment
   137  	// variables.
   138  	EnvironmentFile string
   139  
   140  	// LabelNamespace provides the namespace under which the labels will be generated.
   141  	LabelNamespace string
   142  
   143  	// CallbackURL is a URL which is called upon successful build to inform about that fact.
   144  	CallbackURL string
   145  
   146  	// ScriptsURL is a URL describing where to fetch the S2I scripts from during build process.
   147  	// This url can be a reference within the builder image if the scheme is specified as image://
   148  	ScriptsURL string
   149  
   150  	// BuilderImageLabels is a map containing the builder image labels for possible adjustment of fields
   151  	// on this object.
   152  	BuilderImageLabels map[string]string
   153  
   154  	// Destination specifies a location where the untar operation will place its artifacts.
   155  	Destination string
   156  
   157  	// WorkingDir describes temporary directory used for downloading sources, scripts and tar operations.
   158  	WorkingDir string
   159  
   160  	// WorkingSourceDir describes the subdirectory off of WorkingDir set up during the repo download
   161  	// that is later used as the root for ignore processing
   162  	WorkingSourceDir string
   163  
   164  	// LayeredBuild describes if this is build which layered scripts and sources on top of BuilderImage.
   165  	LayeredBuild bool
   166  
   167  	// Operate quietly. Progress and assemble script output are not reported, only fatal errors.
   168  	// (default: false).
   169  	Quiet bool
   170  
   171  	// ForceCopy results in only the file SCM plugin being used (i.e. no `git clone`); allows for empty directories to be included
   172  	// in resulting image (since git does not support that).
   173  	// (default: false).
   174  	ForceCopy bool
   175  
   176  	// Specify a relative directory inside the application repository that should
   177  	// be used as a root directory for the application.
   178  	ContextDir string
   179  
   180  	// AllowedUIDs is a list of user ranges of users allowed to run the builder image.
   181  	// If a range is specified and the builder (or runtime) image uses a non-numeric
   182  	// user or a user that is outside the specified range, then the build fails.
   183  	AllowedUIDs user.RangeList
   184  
   185  	// AssembleUser specifies the user to run the assemble script in container
   186  	AssembleUser string
   187  
   188  	// RunImage will trigger a "docker run ..." invocation of the produced image so the user
   189  	// can see if it operates as he would expect
   190  	RunImage bool
   191  
   192  	// Usage allows for properly shortcircuiting s2i logic when `s2i usage` is invoked
   193  	Usage bool
   194  
   195  	// Injections specifies a list source/destination folders that are injected to
   196  	// the container that runs assemble.
   197  	// All files we inject will be truncated after the assemble script finishes.
   198  	Injections VolumeList
   199  
   200  	// CGroupLimits describes the cgroups limits that will be applied to any containers
   201  	// run by s2i.
   202  	CGroupLimits *CGroupLimits
   203  
   204  	// DropCapabilities contains a list of capabilities to drop when executing containers
   205  	DropCapabilities []string
   206  
   207  	// ScriptDownloadProxyConfig optionally specifies the http and https proxy
   208  	// to use when downloading scripts
   209  	ScriptDownloadProxyConfig *ProxyConfig
   210  
   211  	// ExcludeRegExp contains a string representation of the regular expression desired for
   212  	// deciding which files to exclude from the tar stream
   213  	ExcludeRegExp string
   214  
   215  	// BlockOnBuild prevents s2i from performing a docker build operation
   216  	// if one is necessary to execute ONBUILD commands, or to layer source code into
   217  	// the container for images that don't have a tar binary available, if the
   218  	// image contains ONBUILD commands that would be executed.
   219  	BlockOnBuild bool
   220  
   221  	// HasOnBuild will be set to true if the builder image contains ONBUILD instructions
   222  	HasOnBuild bool
   223  
   224  	// BuildVolumes specifies a list of volumes to mount to container running the
   225  	// build.
   226  	BuildVolumes []string
   227  
   228  	// Labels specify labels and their values to be applied to the resulting image. Label keys
   229  	// must have non-zero length. The labels defined here override generated labels in case
   230  	// they have the same name.
   231  	Labels map[string]string
   232  
   233  	// SourceInfo provides the info about the source to be built rather than relying
   234  	// on the Downloader to retrieve it.
   235  	SourceInfo *git.SourceInfo
   236  
   237  	// SecurityOpt are passed as options to the docker containers launched by s2i.
   238  	SecurityOpt []string
   239  
   240  	// KeepSymlinks indicates to copy symlinks as symlinks. Default behavior is to follow
   241  	// symlinks and copy files by content.
   242  	KeepSymlinks bool
   243  
   244  	// AsDockerfile indicates the path where the Dockerfile should be written instead of building
   245  	// a new image.
   246  	AsDockerfile string
   247  
   248  	// ImageWorkDir is the default working directory for the builder image.
   249  	ImageWorkDir string
   250  
   251  	// ImageScriptsURL is the default location to find the assemble/run scripts for a builder image.
   252  	// This url can be a reference within the builder image if the scheme is specified as image://
   253  	ImageScriptsURL string
   254  	// AddHost Add a line to /etc/hosts for test purpose or private use in LAN. Its format is host:IP,muliple hosts can be added  by using multiple --add-host
   255  	AddHost []string
   256  
   257  	// AssembleRuntimeUser specifies the user to run the assemble-runtime script in container
   258  	AssembleRuntimeUser string
   259  }
   260  
   261  // EnvironmentSpec specifies a single environment variable.
   262  type EnvironmentSpec struct {
   263  	Name  string
   264  	Value string
   265  }
   266  
   267  // EnvironmentList contains list of environment variables.
   268  type EnvironmentList []EnvironmentSpec
   269  
   270  // ProxyConfig holds proxy configuration.
   271  type ProxyConfig struct {
   272  	HTTPProxy  *url.URL
   273  	HTTPSProxy *url.URL
   274  }
   275  
   276  // CGroupLimits holds limits used to constrain container resources.
   277  type CGroupLimits struct {
   278  	MemoryLimitBytes int64
   279  	CPUShares        int64
   280  	CPUPeriod        int64
   281  	CPUQuota         int64
   282  	MemorySwap       int64
   283  	Parent           string
   284  }
   285  
   286  // VolumeSpec represents a single volume mount point.
   287  type VolumeSpec struct {
   288  	// Source is a reference to the volume source.
   289  	Source string
   290  	// Destination is the path to mount the volume to - absolute or relative.
   291  	Destination string
   292  	// Keep indicates if the mounted data should be kept in the final image.
   293  	Keep bool
   294  }
   295  
   296  // VolumeList contains list of VolumeSpec.
   297  type VolumeList []VolumeSpec
   298  
   299  // DockerConfig contains the configuration for a Docker connection.
   300  type DockerConfig struct {
   301  	// Endpoint is the docker network endpoint or socket
   302  	Endpoint string
   303  
   304  	// CertFile is the certificate file path for a TLS connection
   305  	CertFile string
   306  
   307  	// KeyFile is the key file path for a TLS connection
   308  	KeyFile string
   309  
   310  	// CAFile is the certificate authority file path for a TLS connection
   311  	CAFile string
   312  
   313  	// UseTLS indicates if TLS must be used
   314  	UseTLS bool
   315  
   316  	// TLSVerify indicates if TLS peer must be verified
   317  	TLSVerify bool
   318  }
   319  
   320  // AuthConfig is our abstraction of the Registry authorization information for whatever
   321  // docker client we happen to be based on
   322  type AuthConfig struct {
   323  	Username      string
   324  	Password      string
   325  	Email         string
   326  	ServerAddress string
   327  }
   328  
   329  // ContainerConfig is the abstraction of the docker client provider (formerly go-dockerclient, now either
   330  // engine-api or kube docker client) container.Config type that is leveraged by s2i or origin
   331  type ContainerConfig struct {
   332  	Labels map[string]string
   333  	Env    []string
   334  }
   335  
   336  // Image is the abstraction of the docker client provider (formerly go-dockerclient, now either
   337  // engine-api or kube docker client) Image type that is leveraged by s2i or origin
   338  type Image struct {
   339  	ID string
   340  	*ContainerConfig
   341  	Config *ContainerConfig
   342  }
   343  
   344  // Result structure contains information from build process.
   345  type Result struct {
   346  
   347  	// Success describes whether the build was successful.
   348  	Success bool
   349  
   350  	// Messages is a list of messages from build process.
   351  	Messages []string
   352  
   353  	// WorkingDir describes temporary directory used for downloading sources, scripts and tar operations.
   354  	WorkingDir string
   355  
   356  	// ImageID describes resulting image ID.
   357  	ImageID string
   358  
   359  	// BuildInfo holds information about the result of a build.
   360  	BuildInfo BuildInfo
   361  }
   362  
   363  // BuildInfo contains information about the build process.
   364  type BuildInfo struct {
   365  	// Stages contains details about each build stage.
   366  	Stages []StageInfo
   367  
   368  	// FailureReason is a camel case reason that is used by the machine to reply
   369  	// back to the OpenShift builder with information why any of the steps in the
   370  	// build failed.
   371  	FailureReason FailureReason
   372  }
   373  
   374  // StageInfo contains details about a build stage.
   375  type StageInfo struct {
   376  	// Name is the identifier for each build stage.
   377  	Name StageName
   378  
   379  	// StartTime identifies when this stage started.
   380  	StartTime time.Time
   381  
   382  	// DurationMilliseconds identifies how long this stage ran.
   383  	DurationMilliseconds int64
   384  
   385  	// Steps contains details about each build step within a build stage.
   386  	Steps []StepInfo
   387  }
   388  
   389  // StageName is the identifier for each build stage.
   390  type StageName string
   391  
   392  // Valid StageNames
   393  const (
   394  	// StagePullImages pulls the docker images.
   395  	StagePullImages StageName = "PullImages"
   396  
   397  	//StageAssemble runs the assemble steps.
   398  	StageAssemble StageName = "Assemble"
   399  
   400  	// StageBuild builds the source.
   401  	StageBuild StageName = "Build"
   402  
   403  	// StageCommit commits the container.
   404  	StageCommit StageName = "CommitContainer"
   405  
   406  	// StageRetrieve retrieves artifacts.
   407  	StageRetrieve StageName = "RetrieveArtifacts"
   408  )
   409  
   410  // StepInfo contains details about a build step.
   411  type StepInfo struct {
   412  	// Name is the identifier for each build step.
   413  	Name StepName
   414  
   415  	// StartTime identifies when this step started.
   416  	StartTime time.Time
   417  
   418  	// DurationMilliseconds identifies how long this step ran.
   419  	DurationMilliseconds int64
   420  }
   421  
   422  // StepName is the identifier for each build step.
   423  type StepName string
   424  
   425  // Valid StepNames
   426  const (
   427  	// StepPullBuilderImage pulls the builder image.
   428  	StepPullBuilderImage StepName = "PullBuilderImage"
   429  
   430  	// StepPullPreviousImage pulls the previous image for an incremental build.
   431  	StepPullPreviousImage StepName = "PullPreviousImage"
   432  
   433  	// StepPullRuntimeImage pull the runtime image.
   434  	StepPullRuntimeImage StepName = "PullRuntimeImage"
   435  
   436  	// StepAssembleBuildScripts runs the assemble scripts.
   437  	StepAssembleBuildScripts StepName = "AssembleBuildScripts"
   438  
   439  	// StepBuildDockerImage builds the Docker image for layered builds.
   440  	StepBuildDockerImage StepName = "BuildDockerImage"
   441  
   442  	// StepCommitContainer commits the container to the builder image.
   443  	StepCommitContainer StepName = "CommitContainer"
   444  
   445  	// StepRetrievePreviousArtifacts restores archived artifacts from the previous build.
   446  	StepRetrievePreviousArtifacts StepName = "RetrievePreviousArtifacts"
   447  )
   448  
   449  // StepFailureReason holds the type of failure that occurred during the build
   450  // process.
   451  type StepFailureReason string
   452  
   453  // StepFailureMessage holds the detailed message of a failure.
   454  type StepFailureMessage string
   455  
   456  // FailureReason holds the type of failure that occurred during the build
   457  // process.
   458  type FailureReason struct {
   459  	Reason  StepFailureReason
   460  	Message StepFailureMessage
   461  }
   462  
   463  // InstallResult structure describes the result of install operation
   464  type InstallResult struct {
   465  
   466  	// Script describes which script this result refers to
   467  	Script string
   468  
   469  	// URL describes from where the script was taken
   470  	URL string
   471  
   472  	// Downloaded describes if download operation happened, this will be true for
   473  	// external scripts, but false for scripts from inside the image
   474  	Downloaded bool
   475  
   476  	// Installed describes if script was installed to upload directory
   477  	Installed bool
   478  
   479  	// Error describes last error encountered during install operation
   480  	Error error
   481  
   482  	// FailedSources is a list of sources that were attempted but failed
   483  	// when downloading this script
   484  	FailedSources []string
   485  }
   486  
   487  // DockerNetworkMode specifies the network mode setting for the docker container
   488  type DockerNetworkMode string
   489  
   490  const (
   491  	// DockerNetworkModeHost places the container in the default (host) network namespace.
   492  	DockerNetworkModeHost DockerNetworkMode = "host"
   493  	// DockerNetworkModeBridge instructs docker to create a network namespace for this container connected to the docker0 bridge via a veth-pair.
   494  	DockerNetworkModeBridge DockerNetworkMode = "bridge"
   495  	// DockerNetworkModeContainerPrefix is the string prefix used by NewDockerNetworkModeContainer.
   496  	DockerNetworkModeContainerPrefix string = "container:"
   497  	// DockerNetworkModeNetworkNamespacePrefix is the string prefix used when sharing a namespace from a CRI-O container.
   498  	DockerNetworkModeNetworkNamespacePrefix string = "netns:"
   499  )
   500  
   501  // NewDockerNetworkModeContainer creates a DockerNetworkMode value which instructs docker to place the container in the network namespace of an existing container.
   502  // It can be used, for instance, to place the s2i container in the network namespace of the infrastructure container of a k8s pod.
   503  func NewDockerNetworkModeContainer(id string) DockerNetworkMode {
   504  	return DockerNetworkMode(DockerNetworkModeContainerPrefix + id)
   505  }
   506  
   507  // PullPolicy specifies a type for the method used to retrieve the Docker image
   508  type PullPolicy string
   509  
   510  // String implements the String() function of pflags.Value so this can be used as
   511  // command line parameter.
   512  // This method is really used just to show the default value when printing help.
   513  // It will not default the configuration.
   514  func (p *PullPolicy) String() string {
   515  	if len(string(*p)) == 0 {
   516  		return string(DefaultBuilderPullPolicy)
   517  	}
   518  	return string(*p)
   519  }
   520  
   521  // Type implements the Type() function of pflags.Value interface
   522  func (p *PullPolicy) Type() string {
   523  	return "string"
   524  }
   525  
   526  // Set implements the Set() function of pflags.Value interface
   527  // The valid options are "always", "never" or "if-not-present"
   528  func (p *PullPolicy) Set(v string) error {
   529  	switch v {
   530  	case "always":
   531  		*p = PullAlways
   532  	case "never":
   533  		*p = PullNever
   534  	case "if-not-present":
   535  		*p = PullIfNotPresent
   536  	default:
   537  		return fmt.Errorf("invalid value %q, valid values are: always, never or if-not-present", v)
   538  	}
   539  	return nil
   540  }
   541  
   542  // IsInvalidFilename verifies if the provided filename contains malicious
   543  // characters.
   544  func IsInvalidFilename(name string) bool {
   545  	return strings.ContainsAny(name, invalidFilenameCharacters)
   546  }
   547  
   548  // Set implements the Set() function of pflags.Value interface.
   549  // This function parses the string that contains source:destination pair.
   550  // When the destination is not specified, the source get copied into current
   551  // working directory in container.
   552  func (l *VolumeList) Set(value string) error {
   553  	volumes := strings.Split(value, ";")
   554  	newVols := make([]VolumeSpec, len(volumes))
   555  	for i, v := range volumes {
   556  		spec, err := l.parseSpec(v)
   557  		if err != nil {
   558  			return err
   559  		}
   560  		newVols[i] = *spec
   561  	}
   562  	*l = append(*l, newVols...)
   563  	return nil
   564  }
   565  
   566  func (l *VolumeList) parseSpec(value string) (*VolumeSpec, error) {
   567  	if len(value) == 0 {
   568  		return nil, errors.New("invalid format, must be source:destination")
   569  	}
   570  	var mount []string
   571  	pos := strings.LastIndex(value, ":")
   572  	if pos == -1 {
   573  		mount = []string{value, ""}
   574  	} else {
   575  		mount = []string{value[:pos], value[pos+1:]}
   576  	}
   577  	mount[0] = strings.Trim(mount[0], `"'`)
   578  	mount[1] = strings.Trim(mount[1], `"'`)
   579  	s := &VolumeSpec{Source: filepath.Clean(mount[0]), Destination: filepath.ToSlash(filepath.Clean(mount[1]))}
   580  	if IsInvalidFilename(s.Source) || IsInvalidFilename(s.Destination) {
   581  		return nil, fmt.Errorf("invalid characters in filename: %q", value)
   582  	}
   583  	return s, nil
   584  }
   585  
   586  // String implements the String() function of pflags.Value interface.
   587  func (l *VolumeList) String() string {
   588  	result := []string{}
   589  	for _, i := range *l {
   590  		result = append(result, strings.Join([]string{i.Source, i.Destination}, ":"))
   591  	}
   592  	return strings.Join(result, ",")
   593  }
   594  
   595  // Type implements the Type() function of pflags.Value interface.
   596  func (l *VolumeList) Type() string {
   597  	return "string"
   598  }
   599  
   600  // Set implements the Set() function of pflags.Value interface.
   601  func (e *EnvironmentList) Set(value string) error {
   602  	parts := strings.SplitN(value, "=", 2)
   603  	if len(parts) != 2 || len(parts[0]) == 0 {
   604  		return fmt.Errorf("invalid environment format %q, must be NAME=VALUE", value)
   605  	}
   606  	if strings.Contains(parts[1], ",") && strings.Contains(parts[1], "=") {
   607  		log.Warningf("DEPRECATED: Use multiple -e flags to specify multiple environment variables instead of comma (%q)", value)
   608  	}
   609  	*e = append(*e, EnvironmentSpec{
   610  		Name:  strings.TrimSpace(parts[0]),
   611  		Value: strings.TrimSpace(parts[1]),
   612  	})
   613  	return nil
   614  }
   615  
   616  // String implements the String() function of pflags.Value interface.
   617  func (e *EnvironmentList) String() string {
   618  	result := []string{}
   619  	for _, i := range *e {
   620  		result = append(result, strings.Join([]string{i.Name, i.Value}, "="))
   621  	}
   622  	return strings.Join(result, ",")
   623  }
   624  
   625  // Type implements the Type() function of pflags.Value interface.
   626  func (e *EnvironmentList) Type() string {
   627  	return "string"
   628  }
   629  
   630  // AsBinds converts the list of volume definitions to go-dockerclient compatible
   631  // list of bind mounts.
   632  func (l *VolumeList) AsBinds() []string {
   633  	result := make([]string, len(*l))
   634  	for index, v := range *l {
   635  		result[index] = strings.Join([]string{v.Source, v.Destination}, ":")
   636  	}
   637  	return result
   638  }