github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/jib/maven.go (about) 1 /* 2 Copyright 2019 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package jib 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 "os/exec" 24 25 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" 26 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log" 28 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/platform" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" 31 ) 32 33 // For testing 34 var ( 35 mavenArgsFunc = mavenArgs 36 mavenBuildArgsFunc = mavenBuildArgs 37 ) 38 39 // Skaffold-Jib depends on functionality introduced with Jib-Maven 1.4.0 40 const MinimumJibMavenVersion = "1.4.0" 41 const MinimumJibMavenVersionForSync = "2.0.0" 42 const MinimumJibMavenVersionForCrossPlatform = "3.2.0" 43 44 // MavenCommand stores Maven executable and wrapper name 45 var MavenCommand = util.CommandWrapper{Executable: "mvn", Wrapper: "mvnw"} 46 47 func (b *Builder) buildJibMavenToDocker(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, deps []*latest.ArtifactDependency, tag string, platforms platform.Matcher) (string, error) { 48 args := GenerateMavenBuildArgs("dockerBuild", tag, artifact, platforms, b.skipTests, b.pushImages, deps, b.artifacts, b.cfg.GetInsecureRegistries(), output.IsColorable(out)) 49 if err := b.runMavenCommand(ctx, out, workspace, args); err != nil { 50 return "", jibToolErr(err) 51 } 52 53 return b.localDocker.ImageID(ctx, tag) 54 } 55 56 func (b *Builder) buildJibMavenToRegistry(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, deps []*latest.ArtifactDependency, tag string, platforms platform.Matcher) (string, error) { 57 args := GenerateMavenBuildArgs("build", tag, artifact, platforms, b.skipTests, b.pushImages, deps, b.artifacts, b.cfg.GetInsecureRegistries(), output.IsColorable(out)) 58 if err := b.runMavenCommand(ctx, out, workspace, args); err != nil { 59 return "", jibToolErr(err) 60 } 61 62 return docker.RemoteDigest(tag, b.cfg, nil) 63 } 64 65 func (b *Builder) runMavenCommand(ctx context.Context, out io.Writer, workspace string, args []string) error { 66 cmd := MavenCommand.CreateCommand(ctx, workspace, args) 67 cmd.Env = append(util.OSEnviron(), b.localDocker.ExtraEnv()...) 68 cmd.Stdout = out 69 cmd.Stderr = out 70 71 log.Entry(ctx).Infof("Building %s: %s, %v", workspace, cmd.Path, cmd.Args) 72 if err := util.RunCmd(ctx, &cmd); err != nil { 73 return fmt.Errorf("maven build failed: %w", err) 74 } 75 76 return nil 77 } 78 79 // getDependenciesMaven finds the source dependencies for the given jib-maven artifact. 80 // All paths are absolute. 81 func getDependenciesMaven(ctx context.Context, workspace string, a *latest.JibArtifact) ([]string, error) { 82 deps, err := getDependencies(ctx, workspace, getCommandMaven(ctx, workspace, a), a) 83 if err != nil { 84 return nil, dependencyErr(JibMaven, workspace, err) 85 } 86 log.Entry(ctx).Debugf("Found dependencies for jib maven artifact: %v", deps) 87 return deps, nil 88 } 89 90 func getCommandMaven(ctx context.Context, workspace string, a *latest.JibArtifact) exec.Cmd { 91 args := mavenArgsFunc(a, MinimumJibMavenVersion) 92 args = append(args, "jib:_skaffold-files-v2", "--quiet", "--batch-mode") 93 94 return MavenCommand.CreateCommand(ctx, workspace, args) 95 } 96 97 func getSyncMapCommandMaven(ctx context.Context, workspace string, a *latest.JibArtifact) *exec.Cmd { 98 cmd := MavenCommand.CreateCommand(ctx, workspace, mavenBuildArgsFunc("_skaffold-sync-map", a, true, false, MinimumJibMavenVersionForSync)) 99 return &cmd 100 } 101 102 // GenerateMavenBuildArgs generates the arguments to Maven for building the project as an image. 103 func GenerateMavenBuildArgs(goal, imageName string, a *latest.JibArtifact, platforms platform.Matcher, skipTests, pushImages bool, deps []*latest.ArtifactDependency, r ArtifactResolver, insecureRegistries map[string]bool, showColors bool) []string { 104 minVersion := MinimumJibMavenVersion 105 if platforms.IsCrossPlatform() { 106 minVersion = MinimumJibMavenVersionForCrossPlatform 107 } 108 args := mavenBuildArgsFunc(goal, a, skipTests, showColors, minVersion) 109 if insecure, err := isOnInsecureRegistry(imageName, insecureRegistries); err == nil && insecure { 110 // jib doesn't support marking specific registries as insecure 111 args = append(args, "-Djib.allowInsecureRegistries=true") 112 } 113 if baseImg, found := baseImageArg(a, r, deps, pushImages); found { 114 args = append(args, baseImg) 115 } 116 if platforms.IsNotEmpty() { 117 args = append(args, fmt.Sprintf("-Djib.from.platforms=%s", platforms.String())) 118 } 119 args = append(args, "-Dimage="+imageName) 120 return args 121 } 122 123 // Do not use directly, use mavenBuildArgsFunc 124 func mavenBuildArgs(goal string, a *latest.JibArtifact, skipTests, showColors bool, minimumVersion string) []string { 125 // Disable jib's rich progress footer on builds. Show colors on normal builds for clearer information, 126 // but use --batch-mode for internal goals to avoid formatting issues 127 var args []string 128 if showColors { 129 args = []string{"-Dstyle.color=always", "-Djansi.passthrough=true", "-Djib.console=plain"} 130 } else { 131 args = []string{"--batch-mode"} 132 } 133 args = append(args, mavenArgsFunc(a, minimumVersion)...) 134 135 if skipTests { 136 args = append(args, "-DskipTests=true") 137 } 138 139 if a.Project == "" { 140 // single-module project 141 args = append(args, "prepare-package", "jib:"+goal) 142 } else { 143 // multi-module project: instruct jib to containerize only the given module 144 args = append(args, "package", "jib:"+goal, "-Djib.containerize="+a.Project) 145 } 146 return args 147 } 148 149 // Do not use directly, use mavenArgsFunc 150 func mavenArgs(a *latest.JibArtifact, minimumVersion string) []string { 151 args := []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + minimumVersion} 152 args = append(args, a.Flags...) 153 154 if a.Project == "" { 155 // single-module project 156 args = append(args, "--non-recursive") 157 } else { 158 // multi-module project 159 args = append(args, "--projects", a.Project, "--also-make") 160 } 161 162 return args 163 }