forked from cloudfoundry/bosh-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compiled_package_applier.go
147 lines (119 loc) · 3.63 KB
/
compiled_package_applier.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
package packages
import (
bc "github.com/cloudfoundry/bosh-agent/agent/applier/bundlecollection"
models "github.com/cloudfoundry/bosh-agent/agent/applier/models"
"github.com/cloudfoundry/bosh-agent/agent/http_blob_provider/blobstore_delegator"
bosherr "github.com/cloudfoundry/bosh-utils/errors"
boshlog "github.com/cloudfoundry/bosh-utils/logger"
boshsys "github.com/cloudfoundry/bosh-utils/system"
)
const logTag = "compiledPackageApplier"
type compiledPackageApplier struct {
packagesBc bc.BundleCollection
// KeepOnly will permanently uninstall packages when operating as owner
packagesBcOwner bool
blobstore blobstore_delegator.BlobstoreDelegator
fs boshsys.FileSystem
logger boshlog.Logger
}
func NewCompiledPackageApplier(
packagesBc bc.BundleCollection,
packagesBcOwner bool,
blobstore blobstore_delegator.BlobstoreDelegator,
fs boshsys.FileSystem,
logger boshlog.Logger,
) Applier {
return &compiledPackageApplier{
packagesBc: packagesBc,
packagesBcOwner: packagesBcOwner,
blobstore: blobstore,
fs: fs,
logger: logger,
}
}
func (s compiledPackageApplier) Prepare(pkg models.Package) error {
s.logger.Debug(logTag, "Preparing package %v", pkg)
pkgBundle, err := s.packagesBc.Get(pkg)
if err != nil {
return bosherr.WrapError(err, "Getting package bundle")
}
pkgInstalled, err := pkgBundle.IsInstalled()
if err != nil {
return bosherr.WrapError(err, "Checking if package is installed")
}
if !pkgInstalled {
err := s.downloadAndInstall(pkg, pkgBundle)
if err != nil {
return err
}
}
return nil
}
func (s compiledPackageApplier) Apply(pkg models.Package) error {
s.logger.Debug(logTag, "Applying package %v", pkg)
err := s.Prepare(pkg)
if err != nil {
return err
}
pkgBundle, err := s.packagesBc.Get(pkg)
if err != nil {
return bosherr.WrapError(err, "Getting package bundle")
}
_, err = pkgBundle.Enable()
if err != nil {
return bosherr.WrapError(err, "Enabling package")
}
return nil
}
func (s *compiledPackageApplier) downloadAndInstall(pkg models.Package, pkgBundle bc.Bundle) error {
file, err := s.blobstore.Get(pkg.Source.Sha1, pkg.Source.SignedURL, pkg.Source.BlobstoreID)
if err != nil {
return bosherr.WrapError(err, "Fetching package blob")
}
defer func() {
if err = s.blobstore.CleanUp("", file); err != nil {
s.logger.Warn(logTag, "Failed to clean up blobstore blob: %s", err.Error())
}
}()
_, err = pkgBundle.Install(file, "")
if err != nil {
return bosherr.WrapError(err, "Installing package directory")
}
return nil
}
func (s *compiledPackageApplier) KeepOnly(pkgs []models.Package) error {
s.logger.Debug(logTag, "Keeping only packages %v", pkgs)
installedBundles, err := s.packagesBc.List()
if err != nil {
return bosherr.WrapError(err, "Retrieving installed bundles")
}
for _, installedBundle := range installedBundles {
var shouldKeep bool
for _, pkg := range pkgs {
pkgBundle, err := s.packagesBc.Get(pkg)
if err != nil {
return bosherr.WrapError(err, "Getting package bundle")
}
if pkgBundle == installedBundle {
shouldKeep = true
break
}
}
if !shouldKeep {
err = installedBundle.Disable()
if err != nil {
return bosherr.WrapError(err, "Disabling package bundle")
}
if s.packagesBcOwner {
// If we uninstall the bundle first, and the disable failed (leaving the symlink),
// then the next time bundle collection will not include bundle in its list
// which means that symlink will never be deleted.
err = installedBundle.Uninstall()
if err != nil {
return bosherr.WrapError(err, "Uninstalling package bundle")
}
}
}
}
return nil
}