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 }