-
Notifications
You must be signed in to change notification settings - Fork 0
/
manager.go
142 lines (120 loc) · 4.21 KB
/
manager.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
// Copyright 2019 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package packaging
import (
"fmt"
"strings"
"github.com/juju/errors"
"github.com/juju/loggo"
"github.com/juju/packaging/v2/config"
"github.com/juju/packaging/v2/manager"
)
var logger = loggo.GetLogger("juju.packaging")
// PackageManagerName describes a package manager.
type PackageManagerName string
// The list of supported package managers.
const (
AptPackageManager PackageManagerName = "apt"
YumPackageManager PackageManagerName = "yum"
ZypperPackageManager PackageManagerName = "zypper"
SnapPackageManager PackageManagerName = "snap"
)
// Dependency is implemented by objects that can provide a series-specific
// list of packages for installing a particular software dependency.
type Dependency interface {
PackageList(series string) ([]Package, error)
}
// Package encapsulates the information required for installing a package.
type Package struct {
// The name of the package to install
Name string
// Additional options to be passed to the package manager.
InstallOptions string
// The package manager to use for installing
PackageManager PackageManagerName
}
func (p *Package) appendInstallOptions(opt ...string) {
p.InstallOptions = strings.TrimSpace(
fmt.Sprintf("%s %s", p.InstallOptions, strings.Join(opt, " ")),
)
}
// MakePackageList returns a list of Package instances for each provided
// package name. All package entries share the same package manager name and
// install options.
func MakePackageList(pm PackageManagerName, opts string, packages ...string) []Package {
var list []Package
for _, pkg := range packages {
list = append(list, Package{
Name: pkg,
InstallOptions: opts,
PackageManager: pm,
})
}
return list
}
// InstallDependency executes the appropriate commands to install the specified
// dependency targeting the provided series.
func InstallDependency(dep Dependency, series string) error {
pkgManagers := make(map[PackageManagerName]manager.PackageManager)
pkgConfigurers := make(map[PackageManagerName]config.PackagingConfigurer)
pkgList, err := dep.PackageList(series)
if err != nil {
return errors.Trace(err)
}
for _, pkg := range pkgList {
pm := pkgManagers[pkg.PackageManager]
if pm == nil {
if pm, err = newPackageManager(pkg.PackageManager); err != nil {
return errors.Annotatef(err, "installing package %q via %q", pkg.Name, pkg.PackageManager)
}
pkgManagers[pkg.PackageManager] = pm
}
pkgConfer, exists := pkgConfigurers[pkg.PackageManager]
if !exists {
if pkgConfer, err = newPackageConfigurer(pkg.PackageManager, series); err != nil {
return errors.Annotatef(err, "installing package %q via %q", pkg.Name, pkg.PackageManager)
}
pkgConfigurers[pkg.PackageManager] = pkgConfer
}
if pkgConfer != nil {
if config.RequiresBackports(series, pkg.Name) {
extraOpts := fmt.Sprintf("--target-release %s-backports", series)
pkg.appendInstallOptions(extraOpts)
}
}
logger.Infof("installing %q via %q", pkg.Name, pkg.PackageManager)
pkgWithOpts := strings.TrimSpace(fmt.Sprintf("%s %s", pkg.InstallOptions, pkg.Name))
if err = pm.Install(pkgWithOpts); err != nil {
return errors.Annotatef(err, "installing package %q via %q", pkg.Name, pkg.PackageManager)
}
}
return nil
}
func newPackageManager(name PackageManagerName) (manager.PackageManager, error) {
switch name {
case AptPackageManager:
return manager.NewAptPackageManager(), nil
case YumPackageManager:
return manager.NewYumPackageManager(), nil
case ZypperPackageManager:
return manager.NewZypperPackageManager(), nil
case SnapPackageManager:
return manager.NewSnapPackageManager(), nil
default:
return nil, errors.NotImplementedf("%s package manager", name)
}
}
func newPackageConfigurer(name PackageManagerName, series string) (config.PackagingConfigurer, error) {
switch name {
case AptPackageManager:
return config.NewAptPackagingConfigurer(series), nil
case YumPackageManager:
return config.NewYumPackagingConfigurer(series), nil
case ZypperPackageManager:
return config.NewZypperPackagingConfigurer(series), nil
case SnapPackageManager:
return nil, nil
default:
return nil, errors.NotImplementedf("%s package configurer", name)
}
}