package kaniko import ( "fmt" "io/ioutil" "os" "os/exec" "strings" "git.dotya.ml/wanderer/drone-kaniko/cmd/artifact" ) type ( // Build defines Docker build parameters. Build struct { Dockerfile string // Docker build Dockerfile Context string // Docker build context Tags []string // Docker build tags Args []string // Docker build args Target string // Docker build target Repo string // Docker build repository Labels []string // Label map SkipTlsVerify bool // Docker skip tls certificate verify for registry SnapshotMode string // Kaniko snapshot mode EnableCache bool // Whether to enable kaniko cache CacheRepo string // Remote repository that will be used to store cached layers CacheTTL int // Cache timeout in hours DigestFile string // Digest file location NoPush bool // Set this flag if you only want to build the image, without pushing to a registry Verbosity string // Log level } // Artifact defines content of artifact file Artifact struct { Tags []string // Docker artifact tags Repo string // Docker artifact repository Registry string // Docker artifact registry RegistryType artifact.RegistryTypeEnum // Rocker artifact registry type ArtifactFile string // Artifact file location } // Plugin defines the Docker plugin parameters. Plugin struct { Build Build // Docker build configuration Artifact Artifact // Artifact file content } ) // Exec executes the plugin step func (p Plugin) Exec() error { if _, err := os.Stat(p.Build.Dockerfile); os.IsNotExist(err) { return fmt.Errorf("dockerfile does not exist at path: %s", p.Build.Dockerfile) } cmdArgs := []string{ fmt.Sprintf("--dockerfile=%s", p.Build.Dockerfile), fmt.Sprintf("--context=dir://%s", p.Build.Context), } if p.Build.Repo == "" { fmt.Println("repository name to publish image not specified, adding '--no-push' flag") cmdArgs = append(cmdArgs, fmt.Sprintf("--no-push")) } else { // Set the destination repository for _, tag := range p.Build.Tags { cmdArgs = append(cmdArgs, fmt.Sprintf("--destination=%s:%s", p.Build.Repo, tag)) } } // Set the build arguments for _, arg := range p.Build.Args { cmdArgs = append(cmdArgs, fmt.Sprintf("--build-arg=%s", arg)) } // Set the labels for _, label := range p.Build.Labels { cmdArgs = append(cmdArgs, fmt.Sprintf("--label=%s", label)) } if p.Build.Target != "" { cmdArgs = append(cmdArgs, fmt.Sprintf("--target=%s", p.Build.Target)) } if p.Build.SkipTlsVerify { cmdArgs = append(cmdArgs, fmt.Sprintf("--skip-tls-verify=true")) } if p.Build.SnapshotMode != "" { cmdArgs = append(cmdArgs, fmt.Sprintf("--snapshotMode=%s", p.Build.SnapshotMode)) } if p.Build.EnableCache == true { cmdArgs = append(cmdArgs, fmt.Sprintf("--cache=true")) if p.Build.CacheRepo != "" { cmdArgs = append(cmdArgs, fmt.Sprintf("--cache-repo=%s", p.Build.CacheRepo)) } } if p.Build.CacheTTL != 0 { cmdArgs = append(cmdArgs, fmt.Sprintf("--cache-ttl=%d", p.Build.CacheTTL)) } if p.Build.DigestFile != "" { cmdArgs = append(cmdArgs, fmt.Sprintf("--digest-file=%s", p.Build.DigestFile)) } if p.Build.NoPush { pushNeeded := true for _, arg := range cmdArgs { if arg == "--no-push" { pushNeeded = false break } } if pushNeeded { cmdArgs = append(cmdArgs, fmt.Sprintf("--no-push")) } } if p.Build.Verbosity != "" { cmdArgs = append(cmdArgs, fmt.Sprintf("--verbosity=%s", p.Build.Verbosity)) } cmd := exec.Command("/kaniko/executor", cmdArgs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr trace(cmd) err := cmd.Run() if err != nil { return err } if p.Build.DigestFile != "" && p.Artifact.ArtifactFile != "" { content, err := ioutil.ReadFile(p.Build.DigestFile) if err != nil { fmt.Fprintf(os.Stderr, "failed to read digest file contents at path: %s with error: %s\n", p.Build.DigestFile, err) } err = artifact.WritePluginArtifactFile(p.Artifact.RegistryType, p.Artifact.ArtifactFile, p.Artifact.Registry, p.Artifact.Repo, string(content), p.Artifact.Tags) if err != nil { fmt.Fprintf(os.Stderr, "failed to write plugin artifact file at path: %s with error: %s\n", p.Artifact.ArtifactFile, err) } } return nil } // trace writes each command to stdout with the command wrapped in an xml // tag so that it can be extracted and displayed in the logs. func trace(cmd *exec.Cmd) { fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " ")) }