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