github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/local/types.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 local 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 24 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build" 25 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/bazel" 26 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/buildpacks" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/custom" 28 dockerbuilder "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/docker" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/jib" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko" 31 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/misc" 32 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/config" 33 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" 34 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph" 35 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log" 36 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/platform" 37 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" 38 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" 39 ) 40 41 // Builder uses the host docker daemon to build and tag the image. 42 type Builder struct { 43 local latest.LocalBuild 44 45 cfg docker.Config 46 localDocker docker.LocalDaemon 47 localCluster bool 48 pushImages bool 49 tryImportMissing bool 50 prune bool 51 pruneChildren bool 52 skipTests bool 53 mode config.RunMode 54 kubeContext string 55 builtImages []string 56 insecureRegistries map[string]bool 57 muted build.Muted 58 localPruner *pruner 59 artifactStore build.ArtifactStore 60 sourceDependencies graph.SourceDependenciesCache 61 } 62 63 type Config interface { 64 docker.Config 65 66 GlobalConfig() string 67 GetKubeContext() string 68 GetCluster() config.Cluster 69 SkipTests() bool 70 Mode() config.RunMode 71 NoPruneChildren() bool 72 Muted() config.Muted 73 PushImages() config.BoolOrUndefined 74 } 75 76 type BuilderContext interface { 77 Config 78 ArtifactStore() build.ArtifactStore 79 SourceDependenciesResolver() graph.SourceDependenciesCache 80 } 81 82 // NewBuilder returns an new instance of a local Builder. 83 func NewBuilder(ctx context.Context, bCtx BuilderContext, buildCfg *latest.LocalBuild) (*Builder, error) { 84 localDocker, err := docker.NewAPIClient(ctx, bCtx) 85 if err != nil { 86 return nil, fmt.Errorf("getting docker client: %w", err) 87 } 88 89 cluster := bCtx.GetCluster() 90 pushFlag := bCtx.PushImages() 91 92 var pushImages bool 93 switch { 94 case pushFlag.Value() != nil: 95 pushImages = *pushFlag.Value() 96 log.Entry(context.TODO()).Debugf("push value set via skaffold build --push flag, --push=%t", *pushFlag.Value()) 97 case buildCfg.Push == nil: 98 pushImages = cluster.PushImages 99 log.Entry(context.TODO()).Debugf("push value not present in NewBuilder, defaulting to %t because cluster.PushImages is %t", pushImages, cluster.PushImages) 100 default: 101 pushImages = *buildCfg.Push 102 } 103 104 tryImportMissing := buildCfg.TryImportMissing 105 106 return &Builder{ 107 local: *buildCfg, 108 cfg: bCtx, 109 kubeContext: bCtx.GetKubeContext(), 110 localDocker: localDocker, 111 localCluster: cluster.Local, 112 pushImages: pushImages, 113 tryImportMissing: tryImportMissing, 114 skipTests: bCtx.SkipTests(), 115 mode: bCtx.Mode(), 116 prune: bCtx.Prune(), 117 pruneChildren: !bCtx.NoPruneChildren(), 118 localPruner: newPruner(localDocker, !bCtx.NoPruneChildren()), 119 insecureRegistries: bCtx.GetInsecureRegistries(), 120 muted: bCtx.Muted(), 121 artifactStore: bCtx.ArtifactStore(), 122 sourceDependencies: bCtx.SourceDependenciesResolver(), 123 }, nil 124 } 125 126 // Prune uses the docker API client to remove all images built with Skaffold 127 func (b *Builder) Prune(ctx context.Context, _ io.Writer) error { 128 var toPrune []string 129 seen := make(map[string]bool) 130 131 for _, img := range b.builtImages { 132 if !seen[img] && !b.localPruner.isPruned(img) { 133 toPrune = append(toPrune, img) 134 seen[img] = true 135 } 136 } 137 _, err := b.localDocker.Prune(ctx, toPrune, b.pruneChildren) 138 return err 139 } 140 141 // artifactBuilder represents a per artifact builder interface 142 type artifactBuilder interface { 143 Build(ctx context.Context, out io.Writer, a *latest.Artifact, tag string, platforms platform.Matcher) (string, error) 144 SupportedPlatforms() platform.Matcher 145 } 146 147 // newPerArtifactBuilder returns an instance of `artifactBuilder` 148 func newPerArtifactBuilder(b *Builder, a *latest.Artifact) (artifactBuilder, error) { 149 switch { 150 case a.DockerArtifact != nil: 151 return dockerbuilder.NewArtifactBuilder(b.localDocker, b.cfg, b.local.UseDockerCLI, b.local.UseBuildkit, b.pushImages, b.artifactStore, b.sourceDependencies), nil 152 153 case a.BazelArtifact != nil: 154 return bazel.NewArtifactBuilder(b.localDocker, b.cfg, b.pushImages), nil 155 156 case a.JibArtifact != nil: 157 return jib.NewArtifactBuilder(b.localDocker, b.cfg, b.pushImages, b.skipTests, b.artifactStore), nil 158 159 case a.CustomArtifact != nil: 160 // required artifacts as environment variables 161 dependencies := util.EnvPtrMapToSlice(docker.ResolveDependencyImages(a.Dependencies, b.artifactStore, true), "=") 162 return custom.NewArtifactBuilder(b.localDocker, b.cfg, b.pushImages, b.skipTests, append(b.retrieveExtraEnv(), dependencies...)), nil 163 164 case a.BuildpackArtifact != nil: 165 return buildpacks.NewArtifactBuilder(b.localDocker, b.pushImages, b.mode, b.artifactStore), nil 166 167 case a.KoArtifact != nil: 168 return ko.NewArtifactBuilder(b.localDocker, b.pushImages, b.mode, b.insecureRegistries), nil 169 170 default: 171 return nil, fmt.Errorf("unexpected type %q for local artifact:\n%s", misc.ArtifactType(a), misc.FormatArtifact(a)) 172 } 173 }