code.cloudfoundry.org/cli@v7.1.0+incompatible/actor/pushaction/apply.go (about) 1 package pushaction 2 3 import ( 4 "os" 5 6 "code.cloudfoundry.org/cli/actor/actionerror" 7 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 8 9 log "github.com/sirupsen/logrus" 10 ) 11 12 const PushRetries = 3 13 14 // Apply use the V2 API to create/update the application settings and 15 // eventually uploads the application bits. 16 // 17 // If multiple buildpacks are being applied to the application, the V3 API is 18 // used to set those buildpacks. 19 func (actor Actor) Apply(config ApplicationConfig, progressBar ProgressBar) (<-chan ApplicationConfig, <-chan Event, <-chan Warnings, <-chan error) { 20 configStream := make(chan ApplicationConfig) 21 eventStream := make(chan Event) 22 warningsStream := make(chan Warnings) 23 errorStream := make(chan error) 24 25 go func() { 26 log.Debug("starting apply go routine") 27 defer close(configStream) 28 defer close(eventStream) 29 defer close(warningsStream) 30 defer close(errorStream) 31 32 var event Event 33 var warnings Warnings 34 var err error 35 36 eventStream <- SettingUpApplication 37 if config.UpdatingApplication() { 38 config, event, warnings, err = actor.UpdateApplication(config) 39 } else { 40 config, event, warnings, err = actor.CreateApplication(config) 41 } 42 43 warningsStream <- warnings 44 if err != nil { 45 errorStream <- err 46 return 47 } 48 eventStream <- event 49 log.Debugf("desired application: %#v", config.DesiredApplication) 50 51 if config.NoRoute { 52 if len(config.CurrentRoutes) > 0 { 53 eventStream <- UnmappingRoutes 54 config, warnings, err = actor.UnmapRoutes(config) 55 warningsStream <- warnings 56 if err != nil { 57 errorStream <- err 58 return 59 } 60 } 61 } else { 62 eventStream <- CreatingAndMappingRoutes 63 64 var createdRoutes bool 65 config, createdRoutes, warnings, err = actor.CreateRoutes(config) 66 warningsStream <- warnings 67 if err != nil { 68 errorStream <- err 69 return 70 } 71 if createdRoutes { 72 log.Debugf("updated desired routes: %#v", config.DesiredRoutes) 73 eventStream <- CreatedRoutes 74 } 75 76 var boundRoutes bool 77 config, boundRoutes, warnings, err = actor.MapRoutes(config) 78 warningsStream <- warnings 79 if err != nil { 80 errorStream <- err 81 return 82 } 83 if boundRoutes { 84 log.Debugf("updated desired routes: %#v", config.DesiredRoutes) 85 eventStream <- BoundRoutes 86 } 87 } 88 89 if len(config.CurrentServices) != len(config.DesiredServices) { 90 eventStream <- ConfiguringServices 91 config, _, warnings, err = actor.BindServices(config) 92 warningsStream <- warnings 93 if err != nil { 94 errorStream <- err 95 return 96 } 97 98 log.Debugf("bound desired services: %#v", config.DesiredServices) 99 eventStream <- BoundServices 100 } 101 102 if config.DropletPath != "" { 103 for count := 0; count < PushRetries; count++ { 104 warnings, err = actor.UploadDroplet(config, config.DropletPath, progressBar, eventStream) 105 warningsStream <- warnings 106 if _, ok := err.(ccerror.PipeSeekError); ok { 107 eventStream <- RetryUpload 108 } else { 109 break 110 } 111 } 112 113 if err != nil { 114 if e, ok := err.(ccerror.PipeSeekError); ok { 115 errorStream <- actionerror.UploadFailedError{Err: e.Err} 116 } else { 117 errorStream <- err 118 } 119 return 120 } 121 } else if config.DesiredApplication.DockerImage == "" { 122 eventStream <- ResourceMatching 123 config, warnings = actor.SetMatchedResources(config) 124 warningsStream <- warnings 125 126 if len(config.UnmatchedResources) > 0 { 127 var archivePath string 128 archivePath, err = actor.CreateArchive(config) 129 if err != nil { 130 errorStream <- err 131 os.RemoveAll(archivePath) 132 return 133 } 134 eventStream <- CreatingArchive 135 defer os.RemoveAll(archivePath) 136 137 for count := 0; count < PushRetries; count++ { 138 warnings, err = actor.UploadPackageWithArchive(config, archivePath, progressBar, eventStream) 139 warningsStream <- warnings 140 if _, ok := err.(ccerror.PipeSeekError); ok { 141 eventStream <- RetryUpload 142 } else { 143 break 144 } 145 } 146 147 if err != nil { 148 if e, ok := err.(ccerror.PipeSeekError); ok { 149 errorStream <- actionerror.UploadFailedError{Err: e.Err} 150 } else { 151 errorStream <- err 152 } 153 return 154 } 155 } else { 156 eventStream <- UploadingApplication 157 warnings, err = actor.UploadPackage(config) 158 warningsStream <- warnings 159 if err != nil { 160 errorStream <- err 161 return 162 } 163 } 164 } else { 165 log.WithField("docker_image", config.DesiredApplication.DockerImage).Debug("skipping file upload") 166 } 167 168 configStream <- config 169 170 log.Debug("completed apply") 171 eventStream <- Complete 172 }() 173 174 return configStream, eventStream, warningsStream, errorStream 175 }