github.com/sleungcy/cli@v7.1.0+incompatible/actor/v7action/package.go (about)

     1  package v7action
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/actor/actionerror"
     9  	"code.cloudfoundry.org/cli/actor/sharedaction"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    12  	"code.cloudfoundry.org/cli/resources"
    13  	log "github.com/sirupsen/logrus"
    14  )
    15  
    16  const (
    17  	DefaultFolderPermissions      = 0755
    18  	DefaultArchiveFilePermissions = 0744
    19  )
    20  
    21  type Package ccv3.Package
    22  
    23  type DockerImageCredentials struct {
    24  	Path     string
    25  	Username string
    26  	Password string
    27  }
    28  
    29  func (actor Actor) CreateDockerPackageByApplication(appGUID string, dockerImageCredentials DockerImageCredentials) (Package, Warnings, error) {
    30  	inputPackage := ccv3.Package{
    31  		Type: constant.PackageTypeDocker,
    32  		Relationships: resources.Relationships{
    33  			constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID},
    34  		},
    35  		DockerImage:    dockerImageCredentials.Path,
    36  		DockerUsername: dockerImageCredentials.Username,
    37  		DockerPassword: dockerImageCredentials.Password,
    38  	}
    39  	pkg, warnings, err := actor.CloudControllerClient.CreatePackage(inputPackage)
    40  	return Package(pkg), Warnings(warnings), err
    41  }
    42  
    43  func (actor Actor) CreateDockerPackageByApplicationNameAndSpace(appName string, spaceGUID string, dockerImageCredentials DockerImageCredentials) (Package, Warnings, error) {
    44  	app, getWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
    45  	if err != nil {
    46  		return Package{}, getWarnings, err
    47  	}
    48  	pkg, warnings, err := actor.CreateDockerPackageByApplication(app.GUID, dockerImageCredentials)
    49  	return pkg, append(getWarnings, warnings...), err
    50  }
    51  
    52  func (actor Actor) CreateAndUploadBitsPackageByApplicationNameAndSpace(appName string, spaceGUID string, bitsPath string) (Package, Warnings, error) {
    53  	app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
    54  	if err != nil {
    55  		return Package{}, allWarnings, err
    56  	}
    57  
    58  	if bitsPath == "" {
    59  		bitsPath, err = os.Getwd()
    60  		if err != nil {
    61  			return Package{}, allWarnings, err
    62  		}
    63  	}
    64  
    65  	info, err := os.Stat(bitsPath)
    66  	if err != nil {
    67  		return Package{}, allWarnings, err
    68  	}
    69  
    70  	var fileResources []sharedaction.Resource
    71  	if info.IsDir() {
    72  		fileResources, err = actor.SharedActor.GatherDirectoryResources(bitsPath)
    73  	} else {
    74  		fileResources, err = actor.SharedActor.GatherArchiveResources(bitsPath)
    75  	}
    76  	if err != nil {
    77  		return Package{}, allWarnings, err
    78  	}
    79  
    80  	// potentially match resources here in the future
    81  
    82  	var archivePath string
    83  	if info.IsDir() {
    84  		archivePath, err = actor.SharedActor.ZipDirectoryResources(bitsPath, fileResources)
    85  	} else {
    86  		archivePath, err = actor.SharedActor.ZipArchiveResources(bitsPath, fileResources)
    87  	}
    88  	if err != nil {
    89  		os.RemoveAll(archivePath)
    90  		return Package{}, allWarnings, err
    91  	}
    92  	defer os.RemoveAll(archivePath)
    93  
    94  	inputPackage := ccv3.Package{
    95  		Type: constant.PackageTypeBits,
    96  		Relationships: resources.Relationships{
    97  			constant.RelationshipTypeApplication: resources.Relationship{GUID: app.GUID},
    98  		},
    99  	}
   100  
   101  	pkg, warnings, err := actor.CloudControllerClient.CreatePackage(inputPackage)
   102  	allWarnings = append(allWarnings, warnings...)
   103  	if err != nil {
   104  		return Package{}, allWarnings, err
   105  	}
   106  
   107  	_, warnings, err = actor.CloudControllerClient.UploadPackage(pkg, archivePath)
   108  	allWarnings = append(allWarnings, warnings...)
   109  	if err != nil {
   110  		return Package{}, allWarnings, err
   111  	}
   112  
   113  	for pkg.State != constant.PackageReady &&
   114  		pkg.State != constant.PackageFailed &&
   115  		pkg.State != constant.PackageExpired {
   116  		time.Sleep(actor.Config.PollingInterval())
   117  		pkg, warnings, err = actor.CloudControllerClient.GetPackage(pkg.GUID)
   118  		allWarnings = append(allWarnings, warnings...)
   119  		if err != nil {
   120  			return Package{}, allWarnings, err
   121  		}
   122  	}
   123  
   124  	if pkg.State == constant.PackageFailed {
   125  		return Package{}, allWarnings, actionerror.PackageProcessingFailedError{}
   126  	} else if pkg.State == constant.PackageExpired {
   127  		return Package{}, allWarnings, actionerror.PackageProcessingExpiredError{}
   128  	}
   129  
   130  	updatedPackage, updatedWarnings, err := actor.PollPackage(Package(pkg))
   131  	return updatedPackage, append(allWarnings, updatedWarnings...), err
   132  }
   133  
   134  func (actor Actor) GetNewestReadyPackageForApplication(app resources.Application) (Package, Warnings, error) {
   135  	ccv3Packages, warnings, err := actor.CloudControllerClient.GetPackages(
   136  		ccv3.Query{
   137  			Key:    ccv3.AppGUIDFilter,
   138  			Values: []string{app.GUID},
   139  		},
   140  		ccv3.Query{
   141  			Key:    ccv3.StatesFilter,
   142  			Values: []string{string(constant.PackageReady)},
   143  		},
   144  		ccv3.Query{
   145  			Key:    ccv3.OrderBy,
   146  			Values: []string{ccv3.CreatedAtDescendingOrder},
   147  		},
   148  	)
   149  
   150  	if err != nil {
   151  		return Package{}, Warnings(warnings), err
   152  	}
   153  
   154  	if len(ccv3Packages) == 0 {
   155  		return Package{}, Warnings(warnings), actionerror.NoEligiblePackagesError{AppName: app.Name}
   156  	}
   157  
   158  	return Package(ccv3Packages[0]), Warnings(warnings), nil
   159  }
   160  
   161  // GetApplicationPackages returns a list of package of an app.
   162  func (actor *Actor) GetApplicationPackages(appName string, spaceGUID string) ([]Package, Warnings, error) {
   163  	app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
   164  	if err != nil {
   165  		return nil, allWarnings, err
   166  	}
   167  
   168  	ccv3Packages, warnings, err := actor.CloudControllerClient.GetPackages(
   169  		ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{app.GUID}},
   170  		ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}},
   171  	)
   172  	allWarnings = append(allWarnings, warnings...)
   173  	if err != nil {
   174  		return nil, allWarnings, err
   175  	}
   176  
   177  	var packages []Package
   178  	for _, ccv3Package := range ccv3Packages {
   179  		packages = append(packages, Package(ccv3Package))
   180  	}
   181  
   182  	return packages, allWarnings, nil
   183  }
   184  
   185  func (actor Actor) CreateBitsPackageByApplication(appGUID string) (Package, Warnings, error) {
   186  	inputPackage := ccv3.Package{
   187  		Type: constant.PackageTypeBits,
   188  		Relationships: resources.Relationships{
   189  			constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID},
   190  		},
   191  	}
   192  
   193  	pkg, warnings, err := actor.CloudControllerClient.CreatePackage(inputPackage)
   194  	if err != nil {
   195  		return Package{}, Warnings(warnings), err
   196  	}
   197  
   198  	return Package(pkg), Warnings(warnings), err
   199  }
   200  
   201  func (actor Actor) UploadBitsPackage(pkg Package, matchedResources []sharedaction.V3Resource, newResources io.Reader, newResourcesLength int64) (Package, Warnings, error) {
   202  	apiResources := make([]ccv3.Resource, 0, len(matchedResources)) // Explicitly done to prevent nils
   203  
   204  	for _, resource := range matchedResources {
   205  		apiResources = append(apiResources, ccv3.Resource(resource))
   206  	}
   207  
   208  	appPkg, warnings, err := actor.CloudControllerClient.UploadBitsPackage(ccv3.Package(pkg), apiResources, newResources, newResourcesLength)
   209  	return Package(appPkg), Warnings(warnings), err
   210  }
   211  
   212  // PollPackage returns a package of an app.
   213  func (actor Actor) PollPackage(pkg Package) (Package, Warnings, error) {
   214  	var allWarnings Warnings
   215  
   216  	for pkg.State != constant.PackageReady && pkg.State != constant.PackageFailed && pkg.State != constant.PackageExpired {
   217  		time.Sleep(actor.Config.PollingInterval())
   218  		ccPkg, warnings, err := actor.CloudControllerClient.GetPackage(pkg.GUID)
   219  		log.WithFields(log.Fields{
   220  			"package_guid": pkg.GUID,
   221  			"state":        pkg.State,
   222  		}).Debug("polling package state")
   223  
   224  		allWarnings = append(allWarnings, warnings...)
   225  		if err != nil {
   226  			return Package{}, allWarnings, err
   227  		}
   228  
   229  		pkg = Package(ccPkg)
   230  	}
   231  
   232  	if pkg.State == constant.PackageFailed {
   233  		return Package{}, allWarnings, actionerror.PackageProcessingFailedError{}
   234  	} else if pkg.State == constant.PackageExpired {
   235  		return Package{}, allWarnings, actionerror.PackageProcessingExpiredError{}
   236  	}
   237  
   238  	return pkg, allWarnings, nil
   239  }
   240  
   241  func (actor Actor) CopyPackage(sourceApp resources.Application, targetApp resources.Application) (Package, Warnings, error) {
   242  	var allWarnings Warnings
   243  	sourcePkg, warnings, err := actor.GetNewestReadyPackageForApplication(sourceApp)
   244  	allWarnings = append(allWarnings, warnings...)
   245  	if err != nil {
   246  		return Package{}, allWarnings, err
   247  	}
   248  	targetPkg, ccv3Warnings, err := actor.CloudControllerClient.CopyPackage(sourcePkg.GUID, targetApp.GUID)
   249  	allWarnings = append(allWarnings, ccv3Warnings...)
   250  	if err != nil {
   251  		return Package{}, allWarnings, err
   252  	}
   253  
   254  	readyPackage, warnings, err := actor.PollPackage(Package(targetPkg))
   255  	allWarnings = append(allWarnings, warnings...)
   256  	if err != nil {
   257  		return Package{}, allWarnings, err
   258  	}
   259  
   260  	return readyPackage, allWarnings, nil
   261  }