github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/actor/pushaction/application.go (about)

     1  package pushaction
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"code.cloudfoundry.org/cli/actor/actionerror"
     7  	"code.cloudfoundry.org/cli/actor/v2action"
     8  	"code.cloudfoundry.org/cli/actor/v3action"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    10  	"code.cloudfoundry.org/cli/types"
    11  	log "github.com/sirupsen/logrus"
    12  )
    13  
    14  type Application struct {
    15  	v2action.Application
    16  	Buildpacks []string
    17  	Stack      v2action.Stack
    18  }
    19  
    20  func (app Application) String() string {
    21  	return fmt.Sprintf("%s, Stack Name: '%s', Buildpacks: %s", app.Application, app.Stack.Name, app.Buildpacks)
    22  }
    23  
    24  func (app *Application) SetStack(stack v2action.Stack) {
    25  	app.Stack = stack
    26  	app.StackGUID = stack.GUID
    27  }
    28  
    29  func (actor Actor) CreateApplication(config ApplicationConfig) (ApplicationConfig, Event, Warnings, error) {
    30  	var warnings Warnings
    31  	log.Debugf("creating application")
    32  	v2App := config.DesiredApplication.Application
    33  	v2App.Buildpack = actor.setBuildpack(config)
    34  
    35  	newApp, v2warnings, err := actor.V2Actor.CreateApplication(v2App)
    36  	warnings = append(warnings, v2warnings...)
    37  	if err != nil {
    38  		log.Errorln("creating application:", err)
    39  		return ApplicationConfig{}, "", Warnings(warnings), err
    40  	}
    41  
    42  	if config.HasV3Buildpacks() {
    43  		v3Warnings, v3Err := actor.updateBuildpacks(config, newApp)
    44  		warnings = append(warnings, v3Warnings...)
    45  		if v3Err != nil {
    46  			return ApplicationConfig{}, "", warnings, v3Err
    47  		}
    48  	}
    49  
    50  	config.DesiredApplication.Application = newApp
    51  	config.CurrentApplication = config.DesiredApplication
    52  
    53  	return config, CreatedApplication, Warnings(warnings), nil
    54  }
    55  
    56  func (actor Actor) UpdateApplication(config ApplicationConfig) (ApplicationConfig, Event, Warnings, error) {
    57  	var warnings Warnings
    58  	log.Debugf("updating application")
    59  	v2App := config.DesiredApplication.Application
    60  	v2App.Buildpack = actor.setBuildpack(config)
    61  
    62  	v2App = actor.ignoreSameState(config, v2App)
    63  	v2App = actor.ignoreSameStackGUID(config, v2App)
    64  
    65  	updatedApp, v2Warnings, err := actor.V2Actor.UpdateApplication(v2App)
    66  	warnings = append(warnings, v2Warnings...)
    67  	if err != nil {
    68  		log.Errorln("updating application:", err)
    69  		return ApplicationConfig{}, "", Warnings(warnings), err
    70  	}
    71  
    72  	if config.HasV3Buildpacks() {
    73  		v3Warnings, v3Err := actor.updateBuildpacks(config, updatedApp)
    74  		warnings = append(warnings, v3Warnings...)
    75  		if v3Err != nil {
    76  			return ApplicationConfig{}, "", warnings, v3Err
    77  		}
    78  	}
    79  
    80  	config.DesiredApplication.Application = updatedApp
    81  	config.CurrentApplication = config.DesiredApplication
    82  
    83  	return config, UpdatedApplication, Warnings(warnings), err
    84  }
    85  
    86  func (actor Actor) FindOrReturnPartialApp(appName string, spaceGUID string) (bool, Application, v2action.Warnings, error) {
    87  	foundApp, appWarnings, err := actor.V2Actor.GetApplicationByNameAndSpace(appName, spaceGUID)
    88  	if _, ok := err.(actionerror.ApplicationNotFoundError); ok {
    89  		log.Warnf("unable to find app %s in current space (GUID: %s)", appName, spaceGUID)
    90  		return false, Application{
    91  			Application: v2action.Application{
    92  				Name:      appName,
    93  				SpaceGUID: spaceGUID,
    94  			},
    95  		}, appWarnings, nil
    96  	} else if err != nil {
    97  		log.WithField("appName", appName).Error("error retrieving app")
    98  		return false, Application{}, appWarnings, err
    99  	}
   100  
   101  	stack, stackWarnings, err := actor.V2Actor.GetStack(foundApp.StackGUID)
   102  	warnings := append(appWarnings, stackWarnings...)
   103  	if err != nil {
   104  		log.Warnf("unable to find app's stack (GUID: %s)", foundApp.StackGUID)
   105  		return false, Application{}, warnings, err
   106  	}
   107  
   108  	app := Application{
   109  		Application: foundApp,
   110  		Stack:       stack,
   111  	}
   112  	return true, app, warnings, err
   113  }
   114  
   115  // For some versions of CC, sending state will always result in CC
   116  // attempting to do perform that request (i.e. started -> start/restart).
   117  // In order to prevent repeated unintended restarts in the middle of a
   118  // push, don't send state. This will be fixed in capi-release 1.48.0.
   119  func (actor Actor) ignoreSameState(config ApplicationConfig, v2App v2action.Application) v2action.Application {
   120  	if config.CurrentApplication.State == config.DesiredApplication.State {
   121  		v2App.State = ""
   122  	}
   123  
   124  	return v2App
   125  }
   126  
   127  // Apps updates with both docker image and stack guids fail. So do not send
   128  // StackGUID unless it is necessary.
   129  func (actor Actor) ignoreSameStackGUID(config ApplicationConfig, v2App v2action.Application) v2action.Application {
   130  	if config.CurrentApplication.StackGUID == config.DesiredApplication.StackGUID {
   131  		v2App.StackGUID = ""
   132  	}
   133  
   134  	return v2App
   135  }
   136  
   137  // If 'buildpacks' is set with only one buildpack, set `buildpack` (singular)
   138  // on the application.
   139  func (Actor) setBuildpack(config ApplicationConfig) types.FilteredString {
   140  	buildpacks := config.DesiredApplication.Buildpacks
   141  
   142  	if len(buildpacks) == 1 {
   143  		filtered := new(types.FilteredString)
   144  		filtered.ParseValue(buildpacks[0])
   145  		return *filtered
   146  	}
   147  
   148  	if buildpacks != nil && len(buildpacks) == 0 {
   149  		filtered := types.FilteredString{IsSet: true}
   150  		return filtered
   151  	}
   152  
   153  	return config.DesiredApplication.Buildpack
   154  }
   155  
   156  func (actor Actor) updateBuildpacks(config ApplicationConfig, v2App v2action.Application) (Warnings, error) {
   157  	var buildpacks []string
   158  	for _, buildpack := range config.DesiredApplication.Buildpacks {
   159  		buildpacks = append(buildpacks, buildpack)
   160  	}
   161  
   162  	v3App := v3action.Application{
   163  		Name:                v2App.Name,
   164  		GUID:                v2App.GUID,
   165  		LifecycleBuildpacks: buildpacks,
   166  		LifecycleType:       constant.AppLifecycleTypeBuildpack,
   167  	}
   168  
   169  	_, warnings, err := actor.V3Actor.UpdateApplication(v3App)
   170  	return Warnings(warnings), err
   171  }