-
Notifications
You must be signed in to change notification settings - Fork 88
/
license_store.go
204 lines (176 loc) · 6.85 KB
/
license_store.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package kotsstore
import (
"bytes"
"fmt"
"io/ioutil"
"path/filepath"
"time"
"github.com/pkg/errors"
gitopstypes "github.com/replicatedhq/kots/pkg/gitops/types"
"github.com/replicatedhq/kots/pkg/logger"
"github.com/replicatedhq/kots/pkg/persistence"
rendertypes "github.com/replicatedhq/kots/pkg/render/types"
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
"github.com/replicatedhq/kotskinds/client/kotsclientset/scheme"
"github.com/rqlite/gorqlite"
serializer "k8s.io/apimachinery/pkg/runtime/serializer/json"
)
func (s *KOTSStore) GetLatestLicenseForApp(appID string) (*kotsv1beta1.License, error) {
db := persistence.MustGetDBSession()
query := `select license from app where id = ?`
rows, err := db.QueryOneParameterized(gorqlite.ParameterizedStatement{
Query: query,
Arguments: []interface{}{appID},
})
if err != nil {
return nil, fmt.Errorf("failed to query: %v: %v", err, rows.Err)
}
if !rows.Next() {
return nil, ErrNotFound
}
var licenseStr gorqlite.NullString
if err := rows.Scan(&licenseStr); err != nil {
return nil, errors.Wrap(err, "failed to scan")
}
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(licenseStr.String), nil, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to decode license yaml")
}
license := obj.(*kotsv1beta1.License)
return license, nil
}
func (s *KOTSStore) GetLicenseForAppVersion(appID string, sequence int64) (*kotsv1beta1.License, error) {
db := persistence.MustGetDBSession()
query := `select kots_license from app_version where app_id = ? and sequence = ?`
rows, err := db.QueryOneParameterized(gorqlite.ParameterizedStatement{
Query: query,
Arguments: []interface{}{appID, sequence},
})
if err != nil {
return nil, fmt.Errorf("failed to query: %v: %v", err, rows.Err)
}
if !rows.Next() {
return nil, ErrNotFound
}
var licenseStr gorqlite.NullString
if err := rows.Scan(&licenseStr); err != nil {
return nil, errors.Wrap(err, "failed to scan")
}
if licenseStr.Valid {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(licenseStr.String), nil, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to decode license yaml")
}
license := obj.(*kotsv1beta1.License)
return license, nil
}
return nil, nil
}
func (s *KOTSStore) GetAllAppLicenses() ([]*kotsv1beta1.License, error) {
db := persistence.MustGetDBSession()
query := `select license from app`
rows, err := db.QueryOne(query)
if err != nil {
return nil, fmt.Errorf("failed to query: %v: %v", err, rows.Err)
}
var licenseStr gorqlite.NullString
licenses := []*kotsv1beta1.License{}
for rows.Next() {
if err := rows.Scan(&licenseStr); err != nil {
return nil, errors.Wrap(err, "failed to scan")
}
if licenseStr.Valid {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(licenseStr.String), nil, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to decode license yaml")
}
license := obj.(*kotsv1beta1.License)
licenses = append(licenses, license)
}
}
return licenses, nil
}
func (s *KOTSStore) UpdateAppLicense(appID string, baseSequence int64, archiveDir string, newLicense *kotsv1beta1.License, originalLicenseData string, channelChanged bool, failOnVersionCreate bool, gitops gitopstypes.DownstreamGitOps, renderer rendertypes.Renderer) (int64, error) {
db := persistence.MustGetDBSession()
statements := []gorqlite.ParameterizedStatement{}
ser := serializer.NewYAMLSerializer(serializer.DefaultMetaFactory, scheme.Scheme, scheme.Scheme)
var b bytes.Buffer
if err := ser.Encode(newLicense, &b); err != nil {
return int64(0), errors.Wrap(err, "failed to encode license")
}
encodedLicense := b.Bytes()
if err := ioutil.WriteFile(filepath.Join(archiveDir, "upstream", "userdata", "license.yaml"), encodedLicense, 0644); err != nil {
return int64(0), errors.Wrap(err, "failed to write new license")
}
// app has the original license data received from the server
statements = append(statements, gorqlite.ParameterizedStatement{
Query: `update app set license = ?, last_license_sync = ?, channel_changed = ? where id = ?`,
Arguments: []interface{}{originalLicenseData, time.Now().Unix(), channelChanged, appID},
})
appVersionStatements, newSeq, err := s.createNewVersionForLicenseChangeStatements(appID, baseSequence, archiveDir, gitops, renderer)
if err != nil {
// ignore error here to prevent a failure to render the current version
// preventing the end-user from updating the application
if failOnVersionCreate {
return int64(0), errors.Wrap(err, "failed to construct app version statements for license sync")
}
logger.Errorf("Failed to construct app version statements for license sync: %v", err)
} else {
statements = append(statements, appVersionStatements...)
}
if wrs, err := db.WriteParameterized(statements); err != nil {
wrErrs := []error{}
for _, wr := range wrs {
wrErrs = append(wrErrs, wr.Err)
}
return int64(0), fmt.Errorf("failed to write: %v: %v", err, wrErrs)
}
return newSeq, nil
}
func (s *KOTSStore) UpdateAppLicenseSyncNow(appID string) error {
db := persistence.MustGetDBSession()
query := `update app set last_license_sync = ? where id = ?`
wr, err := db.WriteOneParameterized(gorqlite.ParameterizedStatement{
Query: query,
Arguments: []interface{}{time.Now().Unix(), appID},
})
if err != nil {
return fmt.Errorf("update app %q license sync time: %v: %v", appID, err, wr.Err)
}
return nil
}
func (s *KOTSStore) createNewVersionForLicenseChangeStatements(appID string, baseSequence int64, archiveDir string, gitops gitopstypes.DownstreamGitOps, renderer rendertypes.Renderer) ([]gorqlite.ParameterizedStatement, int64, error) {
registrySettings, err := s.GetRegistryDetailsForApp(appID)
if err != nil {
return nil, int64(0), errors.Wrap(err, "failed to get registry settings for app")
}
app, err := s.GetApp(appID)
if err != nil {
return nil, int64(0), errors.Wrap(err, "failed to get app")
}
downstreams, err := s.ListDownstreamsForApp(appID)
if err != nil {
return nil, int64(0), errors.Wrap(err, "failed to list downstreams")
}
nextAppSequence, err := s.GetNextAppSequence(appID)
if err != nil {
return nil, int64(0), errors.Wrap(err, "failed to get next app sequence")
}
if err := renderer.RenderDir(rendertypes.RenderDirOptions{
ArchiveDir: archiveDir,
App: app,
Downstreams: downstreams,
RegistrySettings: registrySettings,
Sequence: nextAppSequence,
}); err != nil {
return nil, int64(0), errors.Wrap(err, "failed to render new version")
}
appVersionStatements, newSequence, err := s.createAppVersionStatements(appID, &baseSequence, archiveDir, "License Change", false, gitops, renderer)
if err != nil {
return nil, int64(0), errors.Wrap(err, "failed to construct app version statements")
}
return appVersionStatements, newSequence, nil
}