-
Notifications
You must be signed in to change notification settings - Fork 205
/
stamp.go
136 lines (110 loc) · 3.85 KB
/
stamp.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
package configadapter
import (
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"get.porter.sh/porter/pkg"
"get.porter.sh/porter/pkg/config"
"get.porter.sh/porter/pkg/context"
"get.porter.sh/porter/pkg/manifest"
"github.com/cnabio/cnab-go/bundle"
"github.com/pkg/errors"
)
// Stamp contains Porter specific metadata about a bundle that we can place
// in the custom section of a bundle.json
type Stamp struct {
// ManifestDigest takes into account all unique data that goes into a
// porter build to help determine if the last build is stale.
// * manifest
// * mixins
// * (TODO) files in current directory
ManifestDigest string `json:"manifestDigest"`
// Mixins used in the bundle.
Mixins map[string]MixinRecord `json:"mixins"`
// Manifest is the base64 encoded porter.yaml.
EncodedManifest string `json:"manifest"`
}
// DecodeManifest base64 decodes the manifest stored in the stamp
func (s Stamp) DecodeManifest() ([]byte, error) {
if s.EncodedManifest == "" {
return nil, errors.New("no Porter manifest was embedded in the bundle")
}
resultB, err := base64.StdEncoding.DecodeString(s.EncodedManifest)
if err != nil {
return nil, errors.Wrapf(err, "could not base64 decode the manifest in the stamp\n%s", s.EncodedManifest)
}
return resultB, nil
}
func (s Stamp) WriteManifest(cxt *context.Context, path string) error {
manifestB, err := s.DecodeManifest()
if err != nil {
return err
}
err = cxt.FileSystem.WriteFile(path, manifestB, 0644)
return errors.Wrapf(err, "could not save decoded manifest to %s", path)
}
// MixinRecord contains information about a mixin used in a bundle
// For now it is a placeholder for data that we would like to include in the future.
type MixinRecord struct{}
func (c *ManifestConverter) GenerateStamp() (Stamp, error) {
stamp := Stamp{}
// Remember the original porter.yaml, base64 encoded to avoid canonical json shenanigans
rawManifest, err := manifest.ReadManifestData(c.Context, config.Name)
if err != nil {
return Stamp{}, err
}
stamp.EncodedManifest = base64.StdEncoding.EncodeToString(rawManifest)
// Remember the mixins used in the bundle
stamp.Mixins = make(map[string]MixinRecord, len(c.Manifest.Mixins))
for _, m := range c.Manifest.Mixins {
stamp.Mixins[m.Name] = MixinRecord{}
}
digest, err := c.DigestManifest()
if err != nil {
// The digest is only used to decide if we need to rebuild, it is not an error condition to not
// have a digest.
fmt.Fprintln(c.Err, errors.Wrap(err, "WARNING: Could not digest the porter manifest file"))
stamp.ManifestDigest = "unknown"
} else {
stamp.ManifestDigest = digest
}
return stamp, nil
}
func (c *ManifestConverter) DigestManifest() (string, error) {
if exists, _ := c.FileSystem.Exists(config.Name); !exists {
return "", errors.Errorf("the specified porter configuration file %s does not exist", config.Name)
}
data, err := c.FileSystem.ReadFile(config.Name)
if err != nil {
return "", errors.Wrapf(err, "could not read manifest at %q", config.Name)
}
v := pkg.Version
data = append(data, v...)
for _, m := range c.Mixins {
data = append(append(data, m.Name...), m.Version...)
}
digest := sha256.Sum256(data)
return hex.EncodeToString(digest[:]), nil
}
func IsPorterBundle(bun bundle.Bundle) bool {
_, ok := bun.Custom[config.CustomPorterKey]
return ok
}
func LoadStamp(bun bundle.Bundle) (Stamp, error) {
data, ok := bun.Custom[config.CustomPorterKey]
if !ok {
return Stamp{}, errors.Errorf("porter stamp (custom.%s) was not present on the bundle", config.CustomPorterKey)
}
dataB, err := json.Marshal(data)
if err != nil {
return Stamp{}, errors.Wrapf(err, "could not marshal the porter stamp %q", string(dataB))
}
stamp := Stamp{}
err = json.Unmarshal(dataB, &stamp)
if err != nil {
return Stamp{}, errors.Wrapf(err, "could not unmarshal the porter stamp %q", string(dataB))
}
return stamp, nil
}