github.com/lukasheimann/cloudfoundrycli@v7.1.0+incompatible/actor/v7action/build.go (about) 1 package v7action 2 3 import ( 4 "errors" 5 "strings" 6 "time" 7 8 "code.cloudfoundry.org/cli/actor/actionerror" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 11 "code.cloudfoundry.org/cli/resources" 12 13 log "github.com/sirupsen/logrus" 14 ) 15 16 type Build struct { 17 GUID string 18 } 19 20 func (actor Actor) StagePackage(packageGUID, appName, spaceGUID string) (<-chan resources.Droplet, <-chan Warnings, <-chan error) { 21 dropletStream := make(chan resources.Droplet) 22 warningsStream := make(chan Warnings) 23 errorStream := make(chan error) 24 go func() { 25 defer close(dropletStream) 26 defer close(warningsStream) 27 defer close(errorStream) 28 29 apps, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{appName}, spaceGUID) 30 warningsStream <- warnings 31 if err != nil { 32 if _, ok := err.(actionerror.ApplicationsNotFoundError); ok { 33 err = actionerror.ApplicationNotFoundError{Name: appName} 34 } 35 errorStream <- err 36 return 37 } 38 app := apps[0] 39 40 pkgs, allWarnings, err := actor.CloudControllerClient.GetPackages(ccv3.Query{ 41 Key: ccv3.AppGUIDFilter, Values: []string{app.GUID}, 42 }) 43 warningsStream <- Warnings(allWarnings) 44 if err != nil { 45 errorStream <- err 46 return 47 } 48 49 if !packageInPackages(packageGUID, pkgs) { 50 err = actionerror.PackageNotFoundInAppError{GUID: packageGUID, AppName: appName} 51 errorStream <- err 52 return 53 } 54 55 build := ccv3.Build{PackageGUID: packageGUID} 56 build, allWarnings, err = actor.CloudControllerClient.CreateBuild(build) 57 warningsStream <- Warnings(allWarnings) 58 59 if err != nil { 60 errorStream <- err 61 return 62 } 63 64 timer := actor.Clock.NewTimer(time.Millisecond) 65 defer timer.Stop() 66 timeout := actor.Clock.After(actor.Config.StagingTimeout()) 67 68 for { 69 select { 70 case <-timeout: 71 errorStream <- actionerror.StagingTimeoutError{AppName: appName, Timeout: actor.Config.StagingTimeout()} 72 return 73 case <-timer.C(): 74 var warnings ccv3.Warnings 75 build, warnings, err = actor.CloudControllerClient.GetBuild(build.GUID) 76 warningsStream <- Warnings(warnings) 77 if err != nil { 78 errorStream <- err 79 return 80 } 81 82 switch build.State { 83 case constant.BuildFailed: 84 if strings.Contains(build.Error, "NoAppDetectedError") { 85 errorStream <- actionerror.StagingFailedNoAppDetectedError{Reason: build.Error} 86 } else { 87 errorStream <- actionerror.StagingFailedError{Reason: build.Error} 88 } 89 return 90 case constant.BuildStaging: 91 timer.Reset(actor.Config.PollingInterval()) 92 default: 93 94 //TODO: uncomment after #150569020 95 // droplet, warnings, err := actor.CloudControllerClient.GetDroplet(build.DropletGUID) 96 // warningsStream <- Warnings(warnings) 97 // if err != nil { 98 // errorStream <- err 99 // return 100 // } 101 102 droplet := resources.Droplet{ 103 GUID: build.DropletGUID, 104 State: constant.DropletState(build.State), 105 CreatedAt: build.CreatedAt, 106 } 107 108 dropletStream <- droplet 109 return 110 } 111 } 112 } 113 }() 114 115 return dropletStream, warningsStream, errorStream 116 } 117 118 func (actor Actor) StageApplicationPackage(packageGUID string) (Build, Warnings, error) { 119 var allWarnings Warnings 120 121 build := ccv3.Build{PackageGUID: packageGUID} 122 build, warnings, err := actor.CloudControllerClient.CreateBuild(build) 123 log.Debug("created build") 124 allWarnings = append(allWarnings, warnings...) 125 if err != nil { 126 return Build{}, allWarnings, err 127 } 128 129 log.Debug("no errors creating build") 130 return Build{GUID: build.GUID}, allWarnings, nil 131 } 132 133 func (actor Actor) PollBuild(buildGUID string, appName string) (resources.Droplet, Warnings, error) { 134 var allWarnings Warnings 135 136 timeout := actor.Clock.After(actor.Config.StagingTimeout()) 137 interval := actor.Clock.NewTimer(time.Millisecond) 138 139 for { 140 select { 141 case <-interval.C(): 142 build, warnings, err := actor.CloudControllerClient.GetBuild(buildGUID) 143 allWarnings = append(allWarnings, warnings...) 144 if err != nil { 145 return resources.Droplet{}, allWarnings, err 146 } 147 148 switch build.State { 149 case constant.BuildFailed: 150 return resources.Droplet{}, allWarnings, errors.New(build.Error) 151 152 case constant.BuildStaged: 153 droplet, warnings, err := actor.CloudControllerClient.GetDroplet(build.DropletGUID) 154 allWarnings = append(allWarnings, warnings...) 155 if err != nil { 156 return resources.Droplet{}, allWarnings, err 157 } 158 159 return resources.Droplet{ 160 GUID: droplet.GUID, 161 State: droplet.State, 162 CreatedAt: droplet.CreatedAt, 163 }, allWarnings, nil 164 } 165 166 interval.Reset(actor.Config.PollingInterval()) 167 168 case <-timeout: 169 return resources.Droplet{}, allWarnings, actionerror.StagingTimeoutError{AppName: appName, Timeout: actor.Config.StagingTimeout()} 170 } 171 } 172 } 173 174 func packageInPackages(targetPkgGUID string, pkgs []ccv3.Package) bool { 175 for i := range pkgs { 176 if pkgs[i].GUID == targetPkgGUID { 177 return true 178 } 179 } 180 return false 181 }