github.com/kubesphere/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 }