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