forked from cloudfoundry/bosh-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
release_manager.go
110 lines (86 loc) · 2.61 KB
/
release_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
package cmd
import (
bosherr "github.com/cloudfoundry/bosh-utils/errors"
"github.com/cppforlife/go-patch/patch"
semver "github.com/cppforlife/go-semi-semantic/version"
boshdir "github.com/cloudfoundry/bosh-cli/director"
boshtpl "github.com/cloudfoundry/bosh-cli/director/template"
boshrel "github.com/cloudfoundry/bosh-cli/release"
)
type ReleaseManager struct {
createReleaseCmd ReleaseCreatingCmd
uploadReleaseCmd ReleaseUploadingCmd
}
type ReleaseUploadingCmd interface {
Run(UploadReleaseOpts) error
}
type ReleaseCreatingCmd interface {
Run(CreateReleaseOpts) (boshrel.Release, error)
}
func NewReleaseManager(
createReleaseCmd ReleaseCreatingCmd,
uploadReleaseCmd ReleaseUploadingCmd,
) ReleaseManager {
return ReleaseManager{createReleaseCmd, uploadReleaseCmd}
}
func (m ReleaseManager) UploadReleases(bytes []byte) ([]byte, error) {
manifest, err := boshdir.NewManifestFromBytes(bytes)
if err != nil {
return nil, bosherr.WrapErrorf(err, "Parsing manifest")
}
var opss patch.Ops
for _, rel := range manifest.Releases {
ops, err := m.createAndUploadRelease(rel)
if err != nil {
return nil, bosherr.WrapErrorf(err, "Processing release '%s/%s'", rel.Name, rel.Version)
}
opss = append(opss, ops)
}
tpl := boshtpl.NewTemplate(bytes)
bytes, err = tpl.Evaluate(boshtpl.Variables{}, opss, boshtpl.EvaluateOpts{})
if err != nil {
return nil, bosherr.WrapErrorf(err, "Updating manifest with created release versions")
}
return bytes, nil
}
func (m ReleaseManager) createAndUploadRelease(rel boshdir.ManifestRelease) (patch.Ops, error) {
var ops patch.Ops
if len(rel.URL) == 0 {
return nil, nil
}
ver, err := semver.NewVersionFromString(rel.Version)
if err != nil {
return nil, err
}
uploadOpts := UploadReleaseOpts{
Name: rel.Name,
Version: VersionArg(ver),
Args: UploadReleaseArgs{URL: URLArg(rel.URL)},
SHA1: rel.SHA1,
}
if rel.Version == "create" {
createOpts := CreateReleaseOpts{
Name: rel.Name,
Directory: DirOrCWDArg{Path: uploadOpts.Args.URL.FilePath()},
TimestampVersion: true,
Force: true,
}
release, err := m.createReleaseCmd.Run(createOpts)
if err != nil {
return nil, err
}
uploadOpts = UploadReleaseOpts{Release: release}
replaceOp := patch.ReplaceOp{
// equivalent to /releases/name=?/version
Path: patch.NewPointer([]patch.Token{
patch.RootToken{},
patch.KeyToken{Key: "releases"},
patch.MatchingIndexToken{Key: "name", Value: rel.Name},
patch.KeyToken{Key: "version"},
}),
Value: release.Version(),
}
ops = append(ops, replaceOp)
}
return ops, m.uploadReleaseCmd.Run(uploadOpts)
}