kubesphere.io/s2irun@v3.2.1+incompatible/pkg/api/types.go (about)

     1  package api
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/opencontainers/go-digest"
     7  	"net/url"
     8  	"path/filepath"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/docker/distribution/reference"
    13  	"github.com/kubesphere/s2irun/pkg/scm/git"
    14  	utilglog "github.com/kubesphere/s2irun/pkg/utils/glog"
    15  	"github.com/kubesphere/s2irun/pkg/utils/user"
    16  )
    17  
    18  var glog = utilglog.StderrLog
    19  
    20  // invalidFilenameCharacters contains a list of character we consider malicious
    21  // when injecting the directories into containers.
    22  const invalidFilenameCharacters = `;*?"<>|%#$!+{}&[],"'` + "`"
    23  
    24  const (
    25  	// PullAlways means that we always attempt to pull the latest image.
    26  	PullAlways PullPolicy = "always"
    27  
    28  	// PullNever means that we never pull an image, but only use a local image.
    29  	PullNever PullPolicy = "never"
    30  
    31  	// PullIfNotPresent means that we pull if the image isn't present on disk.
    32  	PullIfNotPresent PullPolicy = "if-not-present"
    33  
    34  	// DefaultBuilderPullPolicy specifies the default pull policy to use
    35  	DefaultBuilderPullPolicy = PullIfNotPresent
    36  
    37  	// DefaultRuntimeImagePullPolicy specifies the default pull policy to use.
    38  	DefaultRuntimeImagePullPolicy = PullIfNotPresent
    39  
    40  	// DefaultPreviousImagePullPolicy specifies policy for pulling the previously
    41  	// build Docker image when doing incremental build
    42  	DefaultPreviousImagePullPolicy = PullIfNotPresent
    43  
    44  	// DefaultTag is the image tag, being applied if none is specified.
    45  	DefaultTag = "latest"
    46  
    47  	// AnnotationBuildResultKey is the filed in job annotations.
    48  	AnnotationBuildResultKey = "s2iBuildResult"
    49  
    50  	// AnnotationBuildSourceKey is the filed in job annotations.
    51  	AnnotationBuildSourceKey = "s2iBuildSource"
    52  
    53  	// Command for pull docker image.
    54  	CommandPull = "docker pull "
    55  
    56  	// Default source branch.
    57  	DefaultBranch = "master"
    58  )
    59  
    60  // Config contains essential fields for performing build.
    61  type Config struct {
    62  	// DisplayName is a result image display-name label. This defaults to the
    63  	// output image name.
    64  	DisplayName string `json:"displayName,omitempty"`
    65  
    66  	// Description is a result image description label. The default is no
    67  	// description.
    68  	Description string `json:"description,omitempty"`
    69  
    70  	// BuilderImage describes which image is used for building the result images.
    71  	BuilderImage string `json:"builderImage,omitempty"`
    72  
    73  	// BuilderImageVersion provides optional version information about the builder image.
    74  	BuilderImageVersion string `json:"builderImageVersion,omitempty"`
    75  
    76  	// BuilderBaseImageVersion provides optional version information about the builder base image.
    77  	BuilderBaseImageVersion string `json:"builderBaseImageVersion,omitempty"`
    78  
    79  	// RuntimeImage specifies the image that will be a base for resulting image
    80  	// and will be used for running an application. By default, BuilderImage is
    81  	// used for building and running, but the latter may be overridden.
    82  	RuntimeImage string `json:"runtimeImage,omitempty"`
    83  
    84  	// RuntimeImagePullPolicy specifies when to pull a runtime image.
    85  	RuntimeImagePullPolicy PullPolicy `json:"runtimeImagePullPolicy,omitempty"`
    86  
    87  	// RuntimeAuthentication holds the authentication information for pulling the
    88  	// runtime Docker images from private repositories.
    89  	RuntimeAuthentication AuthConfig `json:"runtimeAuthentication,omitempty"`
    90  
    91  	// RuntimeArtifacts specifies a list of source/destination pairs that will
    92  	// be copied from builder to a runtime image. Source can be a file or
    93  	// directory. Destination must be a directory. Regardless whether it
    94  	// is an absolute or relative path, it will be placed into image's WORKDIR.
    95  	// Destination also can be empty or equals to ".", in this case it just
    96  	// refers to a root of WORKDIR.
    97  	// In case it's empty, S2I will try to get this list from
    98  	// io.openshift.s2i.assemble-input-files label on a RuntimeImage.
    99  	RuntimeArtifacts VolumeList `json:"runtimeArtifacts,omitempty"`
   100  
   101  	// DockerConfig describes how to access host docker daemon.
   102  	DockerConfig *DockerConfig `json:"dockerConfig,omitempty"`
   103  
   104  	// PullAuthentication holds the authentication information for pulling the
   105  	// Docker images from private repositories
   106  	PullAuthentication AuthConfig `json:"pullAuthentication,omitempty"`
   107  
   108  	// PullAuthentication holds the authentication information for pulling the
   109  	// Docker images from private repositories
   110  	PushAuthentication AuthConfig `json:"pushAuthentication,omitempty"`
   111  
   112  	// IncrementalAuthentication holds the authentication information for pulling the
   113  	// previous image from private repositories
   114  	IncrementalAuthentication AuthConfig `json:"incrementalAuthentication,omitempty"`
   115  
   116  	// DockerNetworkMode is used to set the docker network setting to --net=container:<id>
   117  	// when the builder is invoked from a container.
   118  	DockerNetworkMode DockerNetworkMode `json:"dockerNetworkMode,omitempty"`
   119  
   120  	// PreserveWorkingDir describes if working directory should be left after processing.
   121  	PreserveWorkingDir bool `json:"preserveWorkingDir,omitempty"`
   122  
   123  	// IgnoreSubmodules determines whether we will attempt to pull in submodules
   124  	// (via --recursive or submodule init)
   125  	IgnoreSubmodules bool `json:"ignoreSubmodules,omitempty"`
   126  
   127  	// Source URL describing the location of sources used to build the result image.
   128  	Source *git.URL `json:"source,omitempty"`
   129  
   130  	// Tag is a result image tag name.
   131  	Tag string `json:"tag,omitempty"`
   132  
   133  	// BuilderPullPolicy specifies when to pull the builder image
   134  	BuilderPullPolicy PullPolicy `json:"builderPullPolicy,omitempty"`
   135  
   136  	// PreviousImagePullPolicy specifies when to pull the previously build image
   137  	// when doing incremental build
   138  	PreviousImagePullPolicy PullPolicy `json:"previousImagePullPolicy,omitempty"`
   139  
   140  	// Incremental describes whether to try to perform incremental build.
   141  	Incremental bool `json:"incremental,omitempty"`
   142  
   143  	// IncrementalFromTag sets an alternative image tag to look for existing
   144  	// artifacts. Tag is used by default if this is not set.
   145  	IncrementalFromTag string `json:"incrementalFromTag,omitempty"`
   146  
   147  	// RemovePreviousImage describes if previous image should be removed after successful build.
   148  	// This applies only to incremental builds.
   149  	RemovePreviousImage bool `json:"removePreviousImage,omitempty"`
   150  
   151  	// Environment is a map of environment variables to be passed to the image.
   152  	Environment EnvironmentList `json:"environment,omitempty"`
   153  
   154  	// LabelNamespace provides the namespace under which the labels will be generated.
   155  	LabelNamespace string `json:"labelNamespace,omitempty"`
   156  
   157  	// CallbackURL is a URL which is called upon successful build to inform about that fact.
   158  	CallbackURL string `json:"callbackURL,omitempty"`
   159  
   160  	// ScriptsURL is a URL describing where to fetch the S2I scripts from during build process.
   161  	// This url can be a reference within the builder image if the scheme is specified as image://
   162  	ScriptsURL string `json:"scriptsURL,omitempty"`
   163  
   164  	// Destination specifies a location where the untar operation will place its artifacts.
   165  	Destination string `json:"destination,omitempty"`
   166  
   167  	// WorkingDir describes temporary directory used for downloading sources, scripts and tar operations.
   168  	WorkingDir string `json:"workingDir,omitempty"`
   169  
   170  	// WorkingSourceDir describes the subdirectory off of WorkingDir set up during the repo download
   171  	// that is later used as the root for ignore processing
   172  	WorkingSourceDir string `json:"workingSourceDir,omitempty"`
   173  
   174  	// LayeredBuild describes if this is build which layered scripts and sources on top of BuilderImage.
   175  	LayeredBuild bool `json:"layeredBuild,omitempty"`
   176  
   177  	// Operate quietly. Progress and assemble script output are not reported, only fatal errors.
   178  	// (default: false).
   179  	Quiet bool `json:"quiet,omitempty"`
   180  
   181  	// ForceCopy results in only the file SCM plugin being used (i.e. no `git clone`); allows for empty directories to be included
   182  	// in resulting image (since git does not support that).
   183  	// (default: false).
   184  	ForceCopy bool `json:"forceCopy,omitempty"`
   185  
   186  	// Specify a relative directory inside the application repository that should
   187  	// be used as a root directory for the application.
   188  	ContextDir string `json:"contextDir,omitempty"`
   189  
   190  	// AllowedUIDs is a list of user ranges of users allowed to run the builder image.
   191  	// If a range is specified and the builder (or runtime) image uses a non-numeric
   192  	// user or a user that is outside the specified range, then the build fails.
   193  	AllowedUIDs user.RangeList `json:"allowedUIDs,omitempty"`
   194  
   195  	// AssembleUser specifies the user to run the assemble script in container
   196  	AssembleUser string `json:"assembleUser,omitempty"`
   197  
   198  	// RunImage will trigger a "docker run ..." invocation of the produced image so the user
   199  	// can see if it operates as he would expect
   200  	RunImage bool `json:"runImage,omitempty"`
   201  
   202  	// Usage allows for properly shortcircuiting s2i logic when `s2i usage` is invoked
   203  	Usage bool `json:"usage,omitempty"`
   204  
   205  	// Injections specifies a list source/destination folders that are injected to
   206  	// the container that runs assemble.
   207  	// All files we inject will be truncated after the assemble script finishes.
   208  	Injections VolumeList `json:"injections,omitempty"`
   209  
   210  	// CGroupLimits describes the cgroups limits that will be applied to any containers
   211  	// run by s2i.
   212  	CGroupLimits *CGroupLimits `json:"cGroupLimits,omitempty"`
   213  
   214  	// DropCapabilities contains a list of capabilities to drop when executing containers
   215  	DropCapabilities []string `json:"dropCapabilities,omitempty"`
   216  
   217  	// ScriptDownloadProxyConfig optionally specifies the http and https proxy
   218  	// to use when downloading scripts
   219  	ScriptDownloadProxyConfig *ProxyConfig `json:"scriptDownloadProxyConfig,omitempty"`
   220  
   221  	// ExcludeRegExp contains a string representation of the regular expression desired for
   222  	// deciding which files to exclude from the tar stream
   223  	ExcludeRegExp string `json:"excludeRegExp,omitempty"`
   224  
   225  	// BlockOnBuild prevents s2i from performing a docker build operation
   226  	// if one is necessary to execute ONBUILD commands, or to layer source code into
   227  	// the container for images that don't have a tar binary available, if the
   228  	// image contains ONBUILD commands that would be executed.
   229  	BlockOnBuild bool `json:"blockOnBuild,omitempty"`
   230  
   231  	// HasOnBuild will be set to true if the builder image contains ONBUILD instructions
   232  	HasOnBuild bool `json:"hasOnBuild,omitempty"`
   233  
   234  	// BuildVolumes specifies a list of volumes to mount to container running the
   235  	// build.
   236  	BuildVolumes []string `json:"buildVolumes,omitempty"`
   237  
   238  	// Labels specify labels and their values to be applied to the resulting image. Label keys
   239  	// must have non-zero length. The labels defined here override generated labels in case
   240  	// they have the same name.
   241  	Labels map[string]string `json:"labels,omitempty"`
   242  
   243  	// SourceInfo provides the info about the source to be built rather than relying
   244  	// on the Downloader to retrieve it.
   245  	SourceInfo *git.SourceInfo `json:"sourceInfo,omitempty"`
   246  
   247  	// SecurityOpt are passed as options to the docker containers launched by s2i.
   248  	SecurityOpt []string `json:"securityOpt,omitempty"`
   249  
   250  	// KeepSymlinks indicates to copy symlinks as symlinks. Default behavior is to follow
   251  	// symlinks and copy files by content.
   252  	KeepSymlinks bool `json:"keepSymlinks,omitempty"`
   253  
   254  	// AsDockerfile indicates the path where the Dockerfile should be written instead of building
   255  	// a new image.
   256  	AsDockerfile string `json:"asDockerfile,omitempty"`
   257  
   258  	// ImageWorkDir is the default working directory for the builder image.
   259  	ImageWorkDir string `json:"imageWorkDir,omitempty"`
   260  
   261  	// ImageScriptsURL is the default location to find the assemble/run scripts for a builder image.
   262  	// This url can be a reference within the builder image if the scheme is specified as image://
   263  	ImageScriptsURL string `json:"imageScriptsURL,omitempty"`
   264  
   265  	// 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
   266  	AddHost []string `json:"addHost,omitempty"`
   267  
   268  	// Export Push the result image to specify image registry in tag
   269  	Export bool `json:"export,omitempty"`
   270  
   271  	// SourceURL is  url of the codes such as https://github.com/a/b.git
   272  	SourceURL string `json:"sourceURL,omitempty"`
   273  
   274  	// IsBinaryURL explain the type of SourceURL.
   275  	// If it is IsBinaryURL, it will download the file directly without using git.
   276  	IsBinaryURL bool `json:"isBinaryURL,omitempty"`
   277  
   278  	// The RevisionId is a branch name or a SHA-1 hash of every important thing about the commit
   279  	RevisionId string `json:"revisionId,omitempty"`
   280  
   281  	// Output build result. If build not in k8s cluster, can not use this field.
   282  	OutputBuildResult bool `json:"outputBuildResult,omitempty"`
   283  }
   284  
   285  // DeepCopyInto to implement k8s api requirement
   286  func (c *Config) DeepCopyInto(out *Config) {
   287  	*out = *c
   288  
   289  	//slice
   290  	if c.DropCapabilities != nil {
   291  		out.DropCapabilities = make([]string, len(c.DropCapabilities))
   292  		copy(out.DropCapabilities, c.DropCapabilities)
   293  	}
   294  	if c.BuildVolumes != nil {
   295  		out.BuildVolumes = make([]string, len(c.BuildVolumes))
   296  		copy(out.BuildVolumes, c.BuildVolumes)
   297  	}
   298  	if c.AddHost != nil {
   299  		out.AddHost = make([]string, len(c.AddHost))
   300  		copy(out.AddHost, c.AddHost)
   301  	}
   302  	if c.SecurityOpt != nil {
   303  		out.SecurityOpt = make([]string, len(c.SecurityOpt))
   304  		copy(out.SecurityOpt, c.SecurityOpt)
   305  	}
   306  
   307  	//pointer
   308  	if c.DockerConfig != nil {
   309  		out.DockerConfig = new(DockerConfig)
   310  		*(out.DockerConfig) = *(c.DockerConfig)
   311  	}
   312  	if c.Source != nil {
   313  		out.Source = new(git.URL)
   314  		*(out.Source) = *(c.Source)
   315  	}
   316  	if c.SourceInfo != nil {
   317  		out.SourceInfo = new(git.SourceInfo)
   318  		*(out.SourceInfo) = *(c.SourceInfo)
   319  	}
   320  	if c.CGroupLimits != nil {
   321  		out.CGroupLimits = new(CGroupLimits)
   322  		*(out.CGroupLimits) = *(c.CGroupLimits)
   323  	}
   324  }
   325  
   326  func (c *Config) DeepCopy() *Config {
   327  	out := new(Config)
   328  	c.DeepCopyInto(out)
   329  	return out
   330  }
   331  
   332  // EnvironmentSpec specifies a single environment variable.
   333  type EnvironmentSpec struct {
   334  	Name  string `json:"name,omitempty"`
   335  	Value string `json:"value,omitempty"`
   336  }
   337  
   338  // EnvironmentList contains list of environment variables.
   339  type EnvironmentList []EnvironmentSpec
   340  
   341  // ProxyConfig holds proxy configuration.
   342  type ProxyConfig struct {
   343  	HTTPProxy  *url.URL
   344  	HTTPSProxy *url.URL
   345  }
   346  
   347  // CGroupLimits holds limits used to constrain container resources.
   348  type CGroupLimits struct {
   349  	MemoryLimitBytes int64  `json:"memoryLimitBytes,omitempty"`
   350  	CPUShares        int64  `json:"cpuShares,omitempty"`
   351  	CPUPeriod        int64  `json:"cpuPeriod,omitempty"`
   352  	CPUQuota         int64  `json:"cpuQuota,omitempty"`
   353  	MemorySwap       int64  `json:"memorySwap,omitempty"`
   354  	Parent           string `json:"parent,omitempty"`
   355  }
   356  
   357  // VolumeSpec represents a single volume mount point.
   358  type VolumeSpec struct {
   359  	// Source is a reference to the volume source.
   360  	Source string `json:"source,omitempty"`
   361  	// Destination is the path to mount the volume to - absolute or relative.
   362  	Destination string `json:"destination,omitempty"`
   363  	// Keep indicates if the mounted data should be kept in the final image.
   364  	Keep bool `json:"keep,omitempty"`
   365  }
   366  
   367  // VolumeList contains list of VolumeSpec.
   368  type VolumeList []VolumeSpec
   369  
   370  // DockerConfig contains the configuration for a Docker connection.
   371  type DockerConfig struct {
   372  	// Endpoint is the docker network endpoint or socket
   373  	Endpoint string `json:"endpoint,omitempty"`
   374  
   375  	// CertFile is the certificate file path for a TLS connection
   376  	CertFile string `json:"certFile,omitempty"`
   377  
   378  	// KeyFile is the key file path for a TLS connection
   379  	KeyFile string `json:"keyFile,omitempty"`
   380  
   381  	// CAFile is the certificate authority file path for a TLS connection
   382  	CAFile string `json:"caFile,omitempty"`
   383  
   384  	// UseTLS indicates if TLS must be used
   385  	UseTLS bool `json:"useTLS,omitempty"`
   386  
   387  	// TLSVerify indicates if TLS peer must be verified
   388  	TLSVerify bool `json:"tlsVerify,omitempty"`
   389  }
   390  
   391  // AuthConfig is our abstraction of the Registry authorization information for whatever
   392  // docker client we happen to be based on
   393  type AuthConfig struct {
   394  	Username      string `json:"username,omitempty"`
   395  	Password      string `json:"password,omitempty"`
   396  	Email         string `json:"email,omitempty"`
   397  	ServerAddress string `json:"serverAddress,omitempty"`
   398  }
   399  
   400  // ContainerConfig is the abstraction of the docker client provider (formerly go-dockerclient, now either
   401  // engine-api or kube docker client) container.Config type that is leveraged by s2i or origin
   402  type ContainerConfig struct {
   403  	Labels map[string]string
   404  	Env    []string
   405  }
   406  
   407  // Image is the abstraction of the docker client provider (formerly go-dockerclient, now either
   408  // engine-api or kube docker client) Image type that is leveraged by s2i or origin
   409  type Image struct {
   410  	ID string
   411  	*ContainerConfig
   412  	Config *ContainerConfig
   413  }
   414  
   415  // Result structure contains information from build process.
   416  type Result struct {
   417  	// Success describes whether the build was successful.
   418  	Success bool
   419  
   420  	// Messages is a list of messages from build process.
   421  	Messages []string
   422  
   423  	// WorkingDir describes temporary directory used for downloading sources, scripts and tar operations.
   424  	WorkingDir string
   425  
   426  	// BuildInfo holds information about the result of a build.
   427  	BuildInfo BuildInfo
   428  
   429  	// ImageInfo describes resulting image info.
   430  	ResultInfo OutputResultInfo
   431  	// Source info.
   432  	SourceInfo SourceInfo
   433  }
   434  
   435  type SourceInfo struct {
   436  	SourceUrl    string `json:"sourceUrl,omitempty"`
   437  	RevisionId   string `json:"revisionId,omitempty"`
   438  	BuilderImage string `json:"builderImage,omitempty"`
   439  	Description  string `json:"description,omitempty"`
   440  
   441  	CommitID       string `json:"commitID,omitempty"`
   442  	CommitterName  string `json:"committerName,omitempty"`
   443  	CommitterEmail string `json:"committerEmail,omitempty"`
   444  
   445  	BinaryName string `json:"binaryName,omitempty"`
   446  	BinarySize uint64 `json:"binarySize,omitempty"`
   447  }
   448  
   449  type OutputResultInfo struct {
   450  	ImageName     string   `json:"imageName,omitempty"`
   451  	ImageID       string   `json:"imageID,omitempty"`
   452  	ImageSize     int64    `json:"imageSize,omitempty"`
   453  	ImageCreated  string   `json:"imageCreated,omitempty"`
   454  	ImageRepoTags []string `json:"imageRepoTags,omitempty"`
   455  	CommandPull   string   `json:"commandPull,omitempty"`
   456  }
   457  
   458  // BuildInfo contains information about the build process.
   459  type BuildInfo struct {
   460  	// Stages contains details about each build stage.
   461  	Stages []StageInfo
   462  
   463  	// FailureReason is a camel case reason that is used by the machine to reply
   464  	// back to the OpenShift builder with information why any of the steps in the
   465  	// build failed.
   466  	FailureReason FailureReason
   467  }
   468  
   469  // StageInfo contains details about a build stage.
   470  type StageInfo struct {
   471  	// Name is the identifier for each build stage.
   472  	Name StageName
   473  
   474  	// StartTime identifies when this stage started.
   475  	StartTime time.Time
   476  
   477  	// DurationMilliseconds identifies how long this stage ran.
   478  	DurationMilliseconds int64
   479  
   480  	// Steps contains details about each build step within a build stage.
   481  	Steps []StepInfo
   482  }
   483  
   484  // StageName is the identifier for each build stage.
   485  type StageName string
   486  
   487  // Valid StageNames
   488  const (
   489  	// StagePullImages pulls the docker images.
   490  	StagePullImages StageName = "PullImages"
   491  
   492  	//StageAssemble runs the assemble steps.
   493  	StageAssemble StageName = "Assemble"
   494  
   495  	// StageBuild builds the source.
   496  	StageBuild StageName = "Build"
   497  
   498  	// StageCommit commits the container.
   499  	StageCommit StageName = "CommitContainer"
   500  
   501  	// StageRetrieve retrieves artifacts.
   502  	StageRetrieve StageName = "RetrieveArtifacts"
   503  )
   504  
   505  // StepInfo contains details about a build step.
   506  type StepInfo struct {
   507  	// Name is the identifier for each build step.
   508  	Name StepName
   509  
   510  	// StartTime identifies when this step started.
   511  	StartTime time.Time
   512  
   513  	// DurationMilliseconds identifies how long this step ran.
   514  	DurationMilliseconds int64
   515  }
   516  
   517  // StepName is the identifier for each build step.
   518  type StepName string
   519  
   520  // Valid StepNames
   521  const (
   522  	// StepPullBuilderImage pulls the builder image.
   523  	StepPullBuilderImage StepName = "PullBuilderImage"
   524  
   525  	// StepPullPreviousImage pulls the previous image for an incremental build.
   526  	StepPullPreviousImage StepName = "PullPreviousImage"
   527  
   528  	// StepPullRuntimeImage pull the runtime image.
   529  	StepPullRuntimeImage StepName = "PullRuntimeImage"
   530  
   531  	// StepAssembleBuildScripts runs the assemble scripts.
   532  	StepAssembleBuildScripts StepName = "AssembleBuildScripts"
   533  
   534  	// StepBuildDockerImage builds the Docker image for layered builds.
   535  	StepBuildDockerImage StepName = "BuildDockerImage"
   536  
   537  	// StepCommitContainer commits the container to the builder image.
   538  	StepCommitContainer StepName = "CommitContainer"
   539  
   540  	// StepRetrievePreviousArtifacts restores archived artifacts from the previous build.
   541  	StepRetrievePreviousArtifacts StepName = "RetrievePreviousArtifacts"
   542  )
   543  
   544  // StepFailureReason holds the type of failure that occurred during the build
   545  // process.
   546  type StepFailureReason string
   547  
   548  // StepFailureMessage holds the detailed message of a failure.
   549  type StepFailureMessage string
   550  
   551  // FailureReason holds the type of failure that occurred during the build
   552  // process.
   553  type FailureReason struct {
   554  	Reason  StepFailureReason
   555  	Message StepFailureMessage
   556  }
   557  
   558  // InstallResult structure describes the result of install operation
   559  type InstallResult struct {
   560  	// Script describes which script this result refers to
   561  	Script string
   562  
   563  	// URL describes from where the script was taken
   564  	URL string
   565  
   566  	// Downloaded describes if download operation happened, this will be true for
   567  	// external scripts, but false for scripts from inside the image
   568  	Downloaded bool
   569  
   570  	// Installed describes if script was installed to upload directory
   571  	Installed bool
   572  
   573  	// Error describes last error encountered during install operation
   574  	Error error
   575  
   576  	// FailedSources is a list of sources that were attempted but failed
   577  	// when downloading this script
   578  	FailedSources []string
   579  }
   580  
   581  // DockerNetworkMode specifies the network mode setting for the docker container
   582  type DockerNetworkMode string
   583  
   584  // Image holds information about an image.
   585  type ImageInfo struct {
   586  	Domain string
   587  	Path   string
   588  	Tag    string
   589  	Digest digest.Digest
   590  	named  reference.Named
   591  }
   592  
   593  const (
   594  	// DockerNetworkModeHost places the container in the default (host) network namespace.
   595  	DockerNetworkModeHost DockerNetworkMode = "host"
   596  	// DockerNetworkModeBridge instructs docker to create a network namespace for this container connected to the docker0 bridge via a veth-pair.
   597  	DockerNetworkModeBridge DockerNetworkMode = "bridge"
   598  	// DockerNetworkModeContainerPrefix is the string prefix used by NewDockerNetworkModeContainer.
   599  	DockerNetworkModeContainerPrefix string = "container:"
   600  	// DockerNetworkModeNetworkNamespacePrefix is the string prefix used when sharing a namespace from a CRI-O container.
   601  	DockerNetworkModeNetworkNamespacePrefix string = "netns:"
   602  )
   603  
   604  // NewDockerNetworkModeContainer creates a DockerNetworkMode value which instructs docker to place the container in the network namespace of an existing container.
   605  // It can be used, for instance, to place the s2i container in the network namespace of the infrastructure container of a k8s pod.
   606  func NewDockerNetworkModeContainer(id string) DockerNetworkMode {
   607  	return DockerNetworkMode(DockerNetworkModeContainerPrefix + id)
   608  }
   609  
   610  // PullPolicy specifies a type for the method used to retrieve the Docker image
   611  type PullPolicy string
   612  
   613  // String implements the String() function of pflags.Value so this can be used as
   614  // command line parameter.
   615  // This method is really used just to show the default value when printing help.
   616  // It will not default the configuration.
   617  func (p *PullPolicy) String() string {
   618  	if len(string(*p)) == 0 {
   619  		return string(DefaultBuilderPullPolicy)
   620  	}
   621  	return string(*p)
   622  }
   623  
   624  // Type implements the Type() function of pflags.Value interface
   625  func (p *PullPolicy) Type() string {
   626  	return "string"
   627  }
   628  
   629  // Set implements the Set() function of pflags.Value interface
   630  // The valid options are "always", "never" or "if-not-present"
   631  func (p *PullPolicy) Set(v string) error {
   632  	switch v {
   633  	case "always":
   634  		*p = PullAlways
   635  	case "never":
   636  		*p = PullNever
   637  	case "if-not-present":
   638  		*p = PullIfNotPresent
   639  	default:
   640  		return fmt.Errorf("invalid value %q, valid values are: always, never or if-not-present", v)
   641  	}
   642  	return nil
   643  }
   644  
   645  // IsInvalidFilename verifies if the provided filename contains malicious
   646  // characters.
   647  func IsInvalidFilename(name string) bool {
   648  	return strings.ContainsAny(name, invalidFilenameCharacters)
   649  }
   650  
   651  // Set implements the Set() function of pflags.Value interface.
   652  // This function parses the string that contains source:destination pair.
   653  // When the destination is not specified, the source get copied into current
   654  // working directory in container.
   655  func (l *VolumeList) Set(value string) error {
   656  	volumes := strings.Split(value, ";")
   657  	newVols := make([]VolumeSpec, len(volumes))
   658  	for i, v := range volumes {
   659  		spec, err := l.parseSpec(v)
   660  		if err != nil {
   661  			return err
   662  		}
   663  		newVols[i] = *spec
   664  	}
   665  	*l = append(*l, newVols...)
   666  	return nil
   667  }
   668  
   669  func (l *VolumeList) parseSpec(value string) (*VolumeSpec, error) {
   670  	if len(value) == 0 {
   671  		return nil, errors.New("invalid format, must be source:destination")
   672  	}
   673  	var mount []string
   674  	pos := strings.LastIndex(value, ":")
   675  	if pos == -1 {
   676  		mount = []string{value, ""}
   677  	} else {
   678  		mount = []string{value[:pos], value[pos+1:]}
   679  	}
   680  	mount[0] = strings.Trim(mount[0], `"'`)
   681  	mount[1] = strings.Trim(mount[1], `"'`)
   682  	s := &VolumeSpec{Source: filepath.Clean(mount[0]), Destination: filepath.ToSlash(filepath.Clean(mount[1]))}
   683  	if IsInvalidFilename(s.Source) || IsInvalidFilename(s.Destination) {
   684  		return nil, fmt.Errorf("invalid characters in filename: %q", value)
   685  	}
   686  	return s, nil
   687  }
   688  
   689  // String implements the String() function of pflags.Value interface.
   690  func (l *VolumeList) String() string {
   691  	result := []string{}
   692  	for _, i := range *l {
   693  		result = append(result, strings.Join([]string{i.Source, i.Destination}, ":"))
   694  	}
   695  	return strings.Join(result, ",")
   696  }
   697  
   698  // Type implements the Type() function of pflags.Value interface.
   699  func (l *VolumeList) Type() string {
   700  	return "string"
   701  }
   702  
   703  // Set implements the Set() function of pflags.Value interface.
   704  func (e *EnvironmentList) Set(value string) error {
   705  	parts := strings.SplitN(value, "=", 2)
   706  	if len(parts) != 2 || len(parts[0]) == 0 {
   707  		return fmt.Errorf("invalid environment format %q, must be NAME=VALUE", value)
   708  	}
   709  	if strings.Contains(parts[1], ",") && strings.Contains(parts[1], "=") {
   710  		glog.Warningf("DEPRECATED: Use multiple -e flags to specify multiple environment variables instead of comma (%q)", value)
   711  	}
   712  	*e = append(*e, EnvironmentSpec{
   713  		Name:  strings.TrimSpace(parts[0]),
   714  		Value: strings.TrimSpace(parts[1]),
   715  	})
   716  	return nil
   717  }
   718  
   719  // String implements the String() function of pflags.Value interface.
   720  func (e *EnvironmentList) String() string {
   721  	result := []string{}
   722  	for _, i := range *e {
   723  		result = append(result, strings.Join([]string{i.Name, i.Value}, "="))
   724  	}
   725  	return strings.Join(result, ",")
   726  }
   727  
   728  // Type implements the Type() function of pflags.Value interface.
   729  func (e *EnvironmentList) Type() string {
   730  	return "string"
   731  }
   732  
   733  // AsBinds converts the list of volume definitions to go-dockerclient compatible
   734  // list of bind mounts.
   735  func (l *VolumeList) AsBinds() []string {
   736  	result := make([]string, len(*l))
   737  	for index, v := range *l {
   738  		result[index] = strings.Join([]string{v.Source, v.Destination}, ":")
   739  	}
   740  	return result
   741  }
   742  
   743  func Parse(originalName, serverAddress string) (ref string, err error) {
   744  
   745  	image, err := parseImage(originalName)
   746  	if err != nil {
   747  		return "", fmt.Errorf("parsing image %q failed: %v", originalName, err)
   748  	}
   749  
   750  	// remove schema if required
   751  	if strings.Contains(serverAddress, "://") {
   752  		protoAddrParts := strings.SplitN(serverAddress, "://", 2)
   753  		serverAddress = protoAddrParts[1]
   754  	}
   755  
   756  	if image.Domain != serverAddress && serverAddress != "" {
   757  		ref = serverAddress + "/" + image.Path + ":" + image.Tag
   758  	} else {
   759  		ref = image.String()
   760  	}
   761  
   762  	return ref, err
   763  }
   764  
   765  // ParseImage returns an Image struct with all the values filled in for a given image.
   766  // example : localhost:5000/nginx:latest, nginx:perl etc.
   767  func parseImage(image string) (*ImageInfo, error) {
   768  
   769  	// Parse the image name and tag.
   770  	named, err := reference.ParseNormalizedNamed(image)
   771  
   772  	if err != nil {
   773  		return nil, fmt.Errorf("parsing image %q failed: %v", image, err)
   774  	}
   775  	// Add the latest lag if they did not provide one.
   776  	named = reference.TagNameOnly(named)
   777  
   778  	i := &ImageInfo{
   779  		named:  named,
   780  		Domain: reference.Domain(named),
   781  		Path:   reference.Path(named),
   782  	}
   783  
   784  	// Add the tag if there was one.
   785  	if tagged, ok := named.(reference.Tagged); ok {
   786  		i.Tag = tagged.Tag()
   787  	}
   788  
   789  	return i, nil
   790  }
   791  
   792  // String returns the string representation of an image.
   793  func (i *ImageInfo) String() string {
   794  	return i.named.String()
   795  }
   796  
   797  // Reference returns either the digest if it is non-empty or the tag for the image.
   798  func (i *ImageInfo) Reference() string {
   799  	if len(i.Digest.String()) > 1 {
   800  		return i.Digest.String()
   801  	}
   802  
   803  	return i.Tag
   804  }