1package state 2 3import ( 4 biagentclient "github.com/cloudfoundry/bosh-agent/agentclient" 5 biblobstore "github.com/cloudfoundry/bosh-cli/blobstore" 6 birelpkg "github.com/cloudfoundry/bosh-cli/release/pkg" 7 bistatepkg "github.com/cloudfoundry/bosh-cli/state/pkg" 8 bosherr "github.com/cloudfoundry/bosh-utils/errors" 9) 10 11type remotePackageCompiler struct { 12 blobstore biblobstore.Blobstore 13 agentClient biagentclient.AgentClient 14 packageRepo bistatepkg.CompiledPackageRepo 15} 16 17func NewRemotePackageCompiler( 18 blobstore biblobstore.Blobstore, 19 agentClient biagentclient.AgentClient, 20 packageRepo bistatepkg.CompiledPackageRepo, 21) bistatepkg.Compiler { 22 return &remotePackageCompiler{ 23 blobstore: blobstore, 24 agentClient: agentClient, 25 packageRepo: packageRepo, 26 } 27} 28 29func (c *remotePackageCompiler) Compile(pkg birelpkg.Compilable) (bistatepkg.CompiledPackageRecord, bool, error) { 30 var record bistatepkg.CompiledPackageRecord 31 32 blobID, err := c.blobstore.Add(pkg.ArchivePath()) 33 if err != nil { 34 return bistatepkg.CompiledPackageRecord{}, false, bosherr.WrapErrorf(err, "Adding release package archive '%s' to blobstore", pkg.ArchivePath()) 35 } 36 37 packageSource := biagentclient.BlobRef{ 38 Name: pkg.Name(), 39 Version: pkg.Fingerprint(), 40 SHA1: pkg.ArchiveDigest(), 41 BlobstoreID: blobID, 42 } 43 44 var isAlreadyCompiled bool 45 46 if !pkg.IsCompiled() { 47 // Resolve dependencies from map of previously compiled packages. 48 // Only install the package's immediate dependencies. 49 packageDependencies := make([]biagentclient.BlobRef, len(pkg.Deps()), len(pkg.Deps())) 50 51 for i, pkgDep := range pkg.Deps() { 52 compiledPackageRecord, found, err := c.packageRepo.Find(pkgDep) 53 if err != nil { 54 return record, false, bosherr.WrapErrorf( 55 err, 56 "Finding compiled package '%s/%s' as pkgDep for '%s/%s'", 57 pkgDep.Name(), 58 pkgDep.Fingerprint(), 59 pkg.Name(), 60 pkg.Fingerprint(), 61 ) 62 } 63 if !found { 64 return record, false, bosherr.Errorf( 65 "Remote compilation failure: Package '%s/%s' requires package '%s/%s', but it has not been compiled", 66 pkg.Name(), 67 pkg.Fingerprint(), 68 pkgDep.Name(), 69 pkgDep.Fingerprint(), 70 ) 71 } 72 packageDependencies[i] = biagentclient.BlobRef{ 73 Name: pkgDep.Name(), 74 Version: pkgDep.Fingerprint(), 75 BlobstoreID: compiledPackageRecord.BlobID, 76 SHA1: compiledPackageRecord.BlobSHA1, 77 } 78 } 79 80 compiledPackageRef, err := c.agentClient.CompilePackage(packageSource, packageDependencies) 81 if err != nil { 82 return record, false, bosherr.WrapErrorf(err, "Remotely compiling package '%s' with the agent", pkg.Name()) 83 } 84 85 record = bistatepkg.CompiledPackageRecord{ 86 BlobID: compiledPackageRef.BlobstoreID, 87 BlobSHA1: compiledPackageRef.SHA1, 88 } 89 } else { 90 isAlreadyCompiled = true 91 92 record = bistatepkg.CompiledPackageRecord{ 93 BlobID: blobID, 94 BlobSHA1: pkg.ArchiveDigest(), 95 } 96 } 97 98 err = c.packageRepo.Save(pkg, record) 99 if err != nil { 100 return record, isAlreadyCompiled, bosherr.WrapErrorf(err, "Saving compiled package record '%#v' of package '%#v'", record, pkg) 101 } 102 103 return record, isAlreadyCompiled, nil 104} 105