github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/actor/v3action/package.go (about)

     1  package v3action
     2  
     3  import (
     4  	"archive/zip"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  	"time"
    11  
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    13  	"code.cloudfoundry.org/cli/cf/errors"
    14  	"code.cloudfoundry.org/gofileutils/fileutils"
    15  )
    16  
    17  type PackageProcessingFailedError struct{}
    18  
    19  func (_ PackageProcessingFailedError) Error() string {
    20  	return "Package failed to process correctly after upload"
    21  }
    22  
    23  type PackageProcessingExpiredError struct{}
    24  
    25  func (_ PackageProcessingExpiredError) Error() string {
    26  	return "Package expired after upload"
    27  }
    28  
    29  type Package ccv3.Package
    30  
    31  func (actor Actor) CreateAndUploadPackageByApplicationNameAndSpace(appName string, spaceGUID string, bitsPath string) (Package, Warnings, error) {
    32  	app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
    33  	if err != nil {
    34  		return Package{}, allWarnings, err
    35  	}
    36  
    37  	inputPackage := ccv3.Package{
    38  		Type: ccv3.PackageTypeBits,
    39  		Relationships: ccv3.Relationships{
    40  			ccv3.ApplicationRelationship: ccv3.Relationship{GUID: app.GUID},
    41  		},
    42  	}
    43  
    44  	tmpZipFilepath, err := ioutil.TempFile("", "cli-package-upload")
    45  	if err != nil {
    46  		return Package{}, allWarnings, err
    47  	}
    48  	defer os.Remove(tmpZipFilepath.Name())
    49  
    50  	err = writeZipFile(bitsPath, tmpZipFilepath)
    51  	if err != nil {
    52  		return Package{}, allWarnings, err
    53  	}
    54  
    55  	pkg, warnings, err := actor.CloudControllerClient.CreatePackage(inputPackage)
    56  	allWarnings = append(allWarnings, warnings...)
    57  	if err != nil {
    58  		return Package{}, allWarnings, err
    59  	}
    60  
    61  	_, warnings, err = actor.CloudControllerClient.UploadPackage(pkg, tmpZipFilepath.Name())
    62  	allWarnings = append(allWarnings, warnings...)
    63  	if err != nil {
    64  		return Package{}, allWarnings, err
    65  	}
    66  
    67  	for pkg.State != ccv3.PackageStateReady &&
    68  		pkg.State != ccv3.PackageStateFailed &&
    69  		pkg.State != ccv3.PackageStateExpired {
    70  		time.Sleep(actor.Config.PollingInterval())
    71  		pkg, warnings, err = actor.CloudControllerClient.GetPackage(pkg.GUID)
    72  		allWarnings = append(allWarnings, warnings...)
    73  		if err != nil {
    74  			return Package{}, allWarnings, err
    75  		}
    76  	}
    77  
    78  	if pkg.State == ccv3.PackageStateFailed {
    79  		return Package{}, allWarnings, PackageProcessingFailedError{}
    80  	} else if pkg.State == ccv3.PackageStateExpired {
    81  		return Package{}, allWarnings, PackageProcessingExpiredError{}
    82  	}
    83  
    84  	return Package(pkg), allWarnings, err
    85  }
    86  
    87  func writeZipFile(dir string, targetFile *os.File) error {
    88  	isEmpty, err := fileutils.IsDirEmpty(dir)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	if isEmpty {
    94  		return errors.NewEmptyDirError(dir)
    95  	}
    96  
    97  	writer := zip.NewWriter(targetFile)
    98  	defer writer.Close()
    99  
   100  	return filepath.Walk(dir, func(filePath string, fileInfo os.FileInfo, err error) error {
   101  		if err != nil {
   102  			return err
   103  		}
   104  		if filePath == dir {
   105  			return nil
   106  		}
   107  
   108  		fileRelativePath, _ := filepath.Rel(dir, filePath)
   109  
   110  		header, err := zip.FileInfoHeader(fileInfo)
   111  		if err != nil {
   112  			return err
   113  		}
   114  
   115  		if runtime.GOOS == "windows" {
   116  			header.SetMode(header.Mode() | 0700)
   117  		}
   118  		header.Name = filepath.ToSlash(fileRelativePath)
   119  		header.Method = zip.Deflate
   120  
   121  		if fileInfo.IsDir() {
   122  			header.Name += "/"
   123  		}
   124  
   125  		zipFilePart, err := writer.CreateHeader(header)
   126  		if err != nil {
   127  			return err
   128  		}
   129  
   130  		if fileInfo.IsDir() {
   131  			return nil
   132  		}
   133  
   134  		file, err := os.Open(filePath)
   135  		if err != nil {
   136  			return err
   137  		}
   138  		defer file.Close()
   139  
   140  		_, err = io.Copy(zipFilePart, file)
   141  		if err != nil {
   142  			return err
   143  		}
   144  
   145  		return nil
   146  	})
   147  }