forked from cloudfoundry-attic/bosh-init
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compiler.go
148 lines (130 loc) · 4.52 KB
/
compiler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package pkg
import (
"os"
"path"
birelpkg "github.com/cloudfoundry/bosh-init/release/pkg"
bistatepkg "github.com/cloudfoundry/bosh-init/state/pkg"
boshblob "github.com/cloudfoundry/bosh-utils/blobstore"
bosherr "github.com/cloudfoundry/bosh-utils/errors"
boshcmd "github.com/cloudfoundry/bosh-utils/fileutil"
boshlog "github.com/cloudfoundry/bosh-utils/logger"
boshsys "github.com/cloudfoundry/bosh-utils/system"
)
type compiler struct {
runner boshsys.CmdRunner
packagesDir string
fileSystem boshsys.FileSystem
compressor boshcmd.Compressor
blobstore boshblob.Blobstore
compiledPackageRepo bistatepkg.CompiledPackageRepo
packageInstaller Installer
logger boshlog.Logger
logTag string
}
func NewPackageCompiler(
runner boshsys.CmdRunner,
packagesDir string,
fileSystem boshsys.FileSystem,
compressor boshcmd.Compressor,
blobstore boshblob.Blobstore,
compiledPackageRepo bistatepkg.CompiledPackageRepo,
packageInstaller Installer,
logger boshlog.Logger,
) bistatepkg.Compiler {
return &compiler{
runner: runner,
packagesDir: packagesDir,
fileSystem: fileSystem,
compressor: compressor,
blobstore: blobstore,
compiledPackageRepo: compiledPackageRepo,
packageInstaller: packageInstaller,
logger: logger,
logTag: "packageCompiler",
}
}
func (c *compiler) Compile(pkg *birelpkg.Package) (record bistatepkg.CompiledPackageRecord, err error) {
c.logger.Debug(c.logTag, "Checking for compiled package '%s/%s'", pkg.Name, pkg.Fingerprint)
record, found, err := c.compiledPackageRepo.Find(*pkg)
if err != nil {
return record, bosherr.WrapErrorf(err, "Attempting to find compiled package '%s'", pkg.Name)
}
if found {
return record, nil
}
c.logger.Debug(c.logTag, "Installing dependencies of package '%s/%s'", pkg.Name, pkg.Fingerprint)
err = c.installPackages(pkg.Dependencies)
if err != nil {
return record, bosherr.WrapErrorf(err, "Installing dependencies of package '%s'", pkg.Name)
}
defer c.fileSystem.RemoveAll(c.packagesDir)
c.logger.Debug(c.logTag, "Compiling package '%s/%s'", pkg.Name, pkg.Fingerprint)
installDir := path.Join(c.packagesDir, pkg.Name)
err = c.fileSystem.MkdirAll(installDir, os.ModePerm)
if err != nil {
return record, bosherr.WrapError(err, "Creating package install dir")
}
packageSrcDir := pkg.ExtractedPath
if !c.fileSystem.FileExists(path.Join(packageSrcDir, "packaging")) {
return record, bosherr.Errorf("Packaging script for package '%s' not found", pkg.Name)
}
cmd := boshsys.Command{
Name: "bash",
Args: []string{"-x", "packaging"},
Env: map[string]string{
"BOSH_COMPILE_TARGET": packageSrcDir,
"BOSH_INSTALL_TARGET": installDir,
"BOSH_PACKAGE_NAME": pkg.Name,
"BOSH_PACKAGES_DIR": c.packagesDir,
"PATH": "/usr/local/bin:/usr/bin:/bin",
},
UseIsolatedEnv: true,
WorkingDir: packageSrcDir,
}
_, _, _, err = c.runner.RunComplexCommand(cmd)
if err != nil {
return record, bosherr.WrapError(err, "Compiling package")
}
tarball, err := c.compressor.CompressFilesInDir(installDir)
if err != nil {
return record, bosherr.WrapError(err, "Compressing compiled package")
}
defer c.compressor.CleanUp(tarball)
blobID, blobSHA1, err := c.blobstore.Create(tarball)
if err != nil {
return record, bosherr.WrapError(err, "Creating blob")
}
record = bistatepkg.CompiledPackageRecord{
BlobID: blobID,
BlobSHA1: blobSHA1,
}
err = c.compiledPackageRepo.Save(*pkg, record)
if err != nil {
return record, bosherr.WrapError(err, "Saving compiled package")
}
return record, nil
}
func (c *compiler) installPackages(packages []*birelpkg.Package) error {
for _, pkg := range packages {
c.logger.Debug(c.logTag, "Checking for compiled package '%s/%s'", pkg.Name, pkg.Fingerprint)
record, found, err := c.compiledPackageRepo.Find(*pkg)
if err != nil {
return bosherr.WrapErrorf(err, "Attempting to find compiled package '%s'", pkg.Name)
}
if !found {
return bosherr.Errorf("Finding compiled package '%s'", pkg.Name)
}
c.logger.Debug(c.logTag, "Installing package '%s/%s'", pkg.Name, pkg.Fingerprint)
compiledPackageRef := CompiledPackageRef{
Name: pkg.Name,
Version: pkg.Fingerprint,
BlobstoreID: record.BlobID,
SHA1: record.BlobSHA1,
}
err = c.packageInstaller.Install(compiledPackageRef, c.packagesDir)
if err != nil {
return bosherr.WrapErrorf(err, "Installing package '%s' into '%s'", pkg.Name, c.packagesDir)
}
}
return nil
}