github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/command/v3/v3_push_command.go (about) 1 package v3 2 3 import ( 4 "code.cloudfoundry.org/cli/actor/pushaction" 5 "code.cloudfoundry.org/cli/actor/sharedaction" 6 "code.cloudfoundry.org/cli/actor/v2action" 7 "code.cloudfoundry.org/cli/actor/v3action" 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 9 "code.cloudfoundry.org/cli/command" 10 "code.cloudfoundry.org/cli/command/flag" 11 sharedV2 "code.cloudfoundry.org/cli/command/v2/shared" 12 "code.cloudfoundry.org/cli/command/v3/shared" 13 "code.cloudfoundry.org/cli/util/progressbar" 14 15 log "github.com/sirupsen/logrus" 16 ) 17 18 //go:generate counterfeiter . ProgressBar 19 20 type ProgressBar interface { 21 pushaction.ProgressBar 22 Complete() 23 Ready() 24 } 25 26 //go:generate counterfeiter . V3PushActor 27 28 type V3PushActor interface { 29 Actualize(state pushaction.PushState, progressBar pushaction.ProgressBar) (<-chan pushaction.PushState, <-chan pushaction.Event, <-chan pushaction.Warnings, <-chan error) 30 Conceptualize(setting pushaction.CommandLineSettings, spaceGUID string) ([]pushaction.PushState, pushaction.Warnings, error) 31 } 32 33 //go:generate counterfeiter . V3PushVersionActor 34 35 type V3PushVersionActor interface { 36 CloudControllerAPIVersion() string 37 } 38 39 type V3PushCommand struct { 40 RequiredArgs flag.AppName `positional-args:"yes"` 41 Buildpacks []string `short:"b" description:"Custom buildpack by name (e.g. my-buildpack) or Git URL (e.g. 'https://github.com/cloudfoundry/java-buildpack.git') or Git URL with a branch or tag (e.g. 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0' for 'v3.3.0' tag). To use built-in buildpacks only, specify 'default' or 'null'"` 42 // Command flag.Command 43 // Domain string 44 DockerImage flag.DockerImage `long:"docker-image" short:"o" description:"Docker image to use (e.g. user/docker-image-name)"` 45 DockerUsername string `long:"docker-username" description:"Repository username; used with password from environment variable CF_DOCKER_PASSWORD"` 46 // DropletPath flag.PathWithExistenceCheck 47 // PathToManifest flag.PathWithExistenceCheck 48 // HealthCheckType flag.HealthCheckType 49 // Hostname string 50 // Instances flag.Instances 51 // DiskQuota flag.Megabytes 52 // Memory flag.Megabytes 53 // NoHostname bool 54 // NoManifest bool 55 NoRoute bool `long:"no-route" description:"Do not map a route to this app"` 56 NoStart bool `long:"no-start" description:"Do not stage and start the app after pushing"` 57 AppPath flag.PathWithExistenceCheck `short:"p" description:"Path to app directory or to a zip file of the contents of the app directory"` 58 // RandomRoute bool 59 // RoutePath flag.RoutePath 60 // StackName string 61 // VarsFilePaths []flag.PathWithExistenceCheck 62 // Vars []template.VarKV 63 // HealthCheckTimeout int 64 dockerPassword interface{} `environmentName:"CF_DOCKER_PASSWORD" environmentDescription:"Password used for private docker repository"` 65 usage interface{} `usage:"cf v3-push APP_NAME [-b BUILDPACK]... [-p APP_PATH] [--no-route] [--no-start]\n cf v3-push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME] [--no-route] [--no-start]"` 66 envCFStagingTimeout interface{} `environmentName:"CF_STAGING_TIMEOUT" environmentDescription:"Max wait time for buildpack staging, in minutes" environmentDefault:"15"` 67 envCFStartupTimeout interface{} `environmentName:"CF_STARTUP_TIMEOUT" environmentDescription:"Max wait time for app instance startup, in minutes" environmentDefault:"5"` 68 69 UI command.UI 70 Config command.Config 71 NOAAClient v3action.NOAAClient 72 Actor V3PushActor 73 VersionActor V3PushVersionActor 74 SharedActor command.SharedActor 75 AppSummaryDisplayer shared.AppSummaryDisplayer 76 PackageDisplayer shared.PackageDisplayer 77 ProgressBar ProgressBar 78 79 OriginalActor OriginalV3PushActor 80 OriginalV2PushActor OriginalV2PushActor 81 } 82 83 func (cmd *V3PushCommand) Setup(config command.Config, ui command.UI) error { 84 if !config.Experimental() { 85 return cmd.OriginalSetup(config, ui) 86 } 87 88 cmd.Config = config 89 cmd.UI = ui 90 cmd.ProgressBar = progressbar.NewProgressBar() 91 92 sharedActor := sharedaction.NewActor(config) 93 cmd.SharedActor = sharedActor 94 95 ccClient, uaaClient, err := shared.NewClients(config, ui, true) 96 if err != nil { 97 return err 98 } 99 v3Actor := v3action.NewActor(ccClient, config, sharedActor, uaaClient) 100 cmd.VersionActor = v3Actor 101 102 ccClientV2, uaaClientV2, err := sharedV2.NewClients(config, ui, true) 103 if err != nil { 104 return err 105 } 106 107 v2Actor := v2action.NewActor(ccClientV2, uaaClientV2, config) 108 cmd.Actor = pushaction.NewActor(v2Actor, v3Actor, sharedActor) 109 110 return nil 111 } 112 113 func (cmd V3PushCommand) Execute(args []string) error { 114 if !cmd.Config.Experimental() { 115 return cmd.OriginalExecute(args) 116 } 117 118 err := command.MinimumAPIVersionCheck(cmd.VersionActor.CloudControllerAPIVersion(), ccversion.MinVersionV3) 119 if err != nil { 120 return err 121 } 122 123 cmd.UI.DisplayWarning(command.ExperimentalWarning) 124 125 err = cmd.SharedActor.CheckTarget(true, true) 126 if err != nil { 127 return err 128 } 129 130 cmd.UI.DisplayText("Getting app info...") 131 132 log.Info("generating the app state") 133 pushState, warnings, err := cmd.Actor.Conceptualize(pushaction.CommandLineSettings{ 134 Buildpacks: cmd.Buildpacks, 135 Name: cmd.RequiredArgs.AppName, 136 ProvidedAppPath: string(cmd.AppPath), 137 }, cmd.Config.TargetedSpace().GUID) 138 cmd.UI.DisplayWarnings(warnings) 139 if err != nil { 140 return err 141 } 142 log.WithField("number of states", len(pushState)).Debug("completed generating state") 143 144 for _, state := range pushState { 145 log.WithField("app_name", state.Application.Name).Info("actualizing") 146 stateStream, eventStream, warningsStream, errorStream := cmd.Actor.Actualize(state, cmd.ProgressBar) 147 _, err = cmd.processApplyStreams(state.Application.Name, stateStream, eventStream, warningsStream, errorStream) 148 if err != nil { 149 return err 150 } 151 } 152 153 return nil 154 } 155 156 func (cmd V3PushCommand) processApplyStreams( 157 appName string, 158 stateStream <-chan pushaction.PushState, 159 eventStream <-chan pushaction.Event, 160 warningsStream <-chan pushaction.Warnings, 161 errorStream <-chan error, 162 ) (pushaction.PushState, error) { 163 var stateClosed, eventClosed, warningsClosed, complete bool 164 var updateState pushaction.PushState 165 166 for { 167 select { 168 case state, ok := <-stateStream: 169 if !ok { 170 log.Debug("processing config stream closed") 171 stateClosed = true 172 break 173 } 174 updateState = state 175 log.Debugf("updated config received: %#v", updateState) 176 case event, ok := <-eventStream: 177 if !ok { 178 log.Debug("processing event stream closed") 179 eventClosed = true 180 break 181 } 182 complete = cmd.processEvent(appName, event) 183 case warnings, ok := <-warningsStream: 184 if !ok { 185 log.Debug("processing warnings stream closed") 186 warningsClosed = true 187 break 188 } 189 cmd.UI.DisplayWarnings(warnings) 190 case err, ok := <-errorStream: 191 if !ok { 192 log.Debug("processing error stream closed") 193 warningsClosed = true 194 break 195 } 196 return pushaction.PushState{}, err 197 } 198 199 if stateClosed && eventClosed && warningsClosed && complete { 200 log.Debug("breaking apply display loop") 201 break 202 } 203 } 204 205 return updateState, nil 206 } 207 208 func (cmd V3PushCommand) processEvent(appName string, event pushaction.Event) bool { 209 log.Infoln("received apply event:", event) 210 211 switch event { 212 case pushaction.CreatedApplication: 213 cmd.UI.DisplayTextWithFlavor("Creating app {{.AppName}}...", map[string]interface{}{ 214 "AppName": appName, 215 }) 216 case pushaction.SkipingApplicationCreation: 217 cmd.UI.DisplayTextWithFlavor("Updating app {{.AppName}}...", map[string]interface{}{ 218 "AppName": appName, 219 }) 220 case pushaction.Complete: 221 return true 222 default: 223 log.WithField("event", event).Debug("ignoring event") 224 } 225 return false 226 }