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 }