github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/runner/v1/deploy.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 v1 18 19 import ( 20 "context" 21 "fmt" 22 "io" 23 "time" 24 25 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants" 26 deployutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util" 27 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event" 28 eventV2 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event/v2" 29 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph" 30 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/instrumentation" 31 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output" 32 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log" 33 ) 34 35 // DeployAndLog deploys a list of already built artifacts and optionally show the logs. 36 func (r *SkaffoldRunner) DeployAndLog(ctx context.Context, out io.Writer, artifacts []graph.Artifact) error { 37 defer r.deployer.GetLogger().Stop() 38 39 // Logs should be retrieved up to just before the deploy 40 r.deployer.GetLogger().SetSince(time.Now()) 41 // First deploy 42 if err := r.Deploy(ctx, out, artifacts); err != nil { 43 return err 44 } 45 46 defer r.deployer.GetAccessor().Stop() 47 48 if err := r.deployer.GetAccessor().Start(ctx, out); err != nil { 49 log.Entry(ctx).Warn("Error starting port forwarding:", err) 50 } 51 52 // Start printing the logs after deploy is finished 53 if err := r.deployer.GetLogger().Start(ctx, out); err != nil { 54 return fmt.Errorf("starting logger: %w", err) 55 } 56 57 if r.runCtx.Tail() || r.runCtx.PortForward() { 58 output.Yellow.Fprintln(out, "Press Ctrl+C to exit") 59 <-ctx.Done() 60 } 61 62 return nil 63 } 64 65 func (r *SkaffoldRunner) Deploy(ctx context.Context, out io.Writer, artifacts []graph.Artifact) error { 66 if r.runCtx.RenderOnly() { 67 return r.Render(ctx, out, artifacts, false, r.runCtx.RenderOutput()) 68 } 69 defer r.deployer.GetStatusMonitor().Reset() 70 71 out, ctx = output.WithEventContext(ctx, out, constants.Deploy, constants.SubtaskIDNone) 72 73 output.Default.Fprintln(out, "Tags used in deployment:") 74 75 for _, artifact := range artifacts { 76 output.Default.Fprintf(out, " - %s -> ", artifact.ImageName) 77 fmt.Fprintln(out, artifact.Tag) 78 } 79 80 var localImages []graph.Artifact 81 for _, a := range artifacts { 82 if isLocal, err := r.isLocalImage(a.ImageName); err != nil { 83 return err 84 } else if isLocal { 85 localImages = append(localImages, a) 86 } 87 } 88 89 if len(localImages) > 0 { 90 log.Entry(ctx).Debug(`Local images can't be referenced by digest. 91 They are tagged and referenced by a unique, local only, tag instead. 92 See https://skaffold.dev/docs/pipeline-stages/taggers/#how-tagging-works`) 93 } 94 95 deployOut, postDeployFn, err := deployutil.WithLogFile(time.Now().Format(deployutil.TimeFormat)+".log", out, r.runCtx.Muted()) 96 if err != nil { 97 return err 98 } 99 100 event.DeployInProgress() 101 eventV2.TaskInProgress(constants.Deploy, "Deploy to cluster") 102 ctx, endTrace := instrumentation.StartTrace(ctx, "Deploy_Deploying") 103 defer endTrace() 104 105 // we only want to register images that are local AND were built by this runner OR forced to load via flag 106 var localAndBuiltImages []graph.Artifact 107 for _, image := range localImages { 108 if r.runCtx.ForceLoadImages() || r.wasBuilt(image.Tag) { 109 localAndBuiltImages = append(localAndBuiltImages, image) 110 } 111 } 112 113 r.deployer.RegisterLocalImages(localAndBuiltImages) 114 err = r.deployer.Deploy(ctx, deployOut, artifacts) 115 r.hasDeployed = true // set even if deploy may have failed, because we want to cleanup any partially created resources 116 postDeployFn() 117 if err != nil { 118 event.DeployFailed(err) 119 eventV2.TaskFailed(constants.Deploy, err) 120 endTrace(instrumentation.TraceEndError(err)) 121 return err 122 } 123 124 statusCheckOut, postStatusCheckFn, err := deployutil.WithStatusCheckLogFile(time.Now().Format(deployutil.TimeFormat)+".log", out, r.runCtx.Muted()) 125 defer postStatusCheckFn() 126 if err != nil { 127 endTrace(instrumentation.TraceEndError(err)) 128 return err 129 } 130 131 event.DeployComplete() 132 if !r.runCtx.Opts.IterativeStatusCheck { 133 // run final aggregated status check only if iterative status check is turned off. 134 if err = r.deployer.GetStatusMonitor().Check(ctx, statusCheckOut); err != nil { 135 eventV2.TaskFailed(constants.Deploy, err) 136 return err 137 } 138 } 139 eventV2.TaskSucceeded(constants.Deploy) 140 return nil 141 } 142 143 func (r *SkaffoldRunner) wasBuilt(tag string) bool { 144 for _, built := range r.Builds { 145 if built.Tag == tag { 146 return true 147 } 148 } 149 return false 150 }