This repository has been archived by the owner on Jan 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 132
/
chart_store_db.go
232 lines (194 loc) · 9.68 KB
/
chart_store_db.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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package store
import (
"database/sql"
"errors"
"fmt"
"sort"
"github.com/cloudfoundry-incubator/stratos/src/jetstream/datastore"
log "github.com/sirupsen/logrus"
)
var (
saveChartVersion = `INSERT INTO helm_charts (endpoint, name, repo_name, version, created, app_version, description, icon_url, chart_url, source_url, digest, is_latest, update_batch) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`
updateChartVersion = `UPDATE helm_charts SET created=$1, app_version=$2, description=$3, icon_url=$4, chart_url=$5, source_url=$6, digest=$7, is_latest=$8, update_batch=$9 WHERE endpoint=$10 AND name=$11 AND repo_name=$12 AND version=$13`
deleteChartVersion = `DELETE FROM helm_charts WHERE endpoint = $1 AND name = $2 and version = $3`
deleteForEndpoint = `DELETE FROM helm_charts WHERE endpoint = $1`
deleteForBatch = `DELETE FROM helm_charts WHERE endpoint = $1 AND name = $2 and update_batch != $3`
renameEndpoint = `UPDATE helm_charts SET repo_name=$1 WHERE endpoint=$2`
getLatestCharts = `SELECT endpoint, name, repo_name, version, created, app_version, description, icon_url, chart_url, source_url, digest, is_latest FROM helm_charts WHERE is_latest = true`
getLatestChart = `SELECT endpoint, name, repo_name, version, created, app_version, description, icon_url, chart_url, source_url, digest, is_latest FROM helm_charts WHERE repo_name = $1 AND name = $2 AND is_latest = true`
getChartVersion = `SELECT endpoint, name, repo_name, version, created, app_version, description, icon_url, chart_url, source_url, digest, is_latest FROM helm_charts WHERE repo_name = $1 AND name = $2 AND version = $3`
getChartVersions = `SELECT endpoint, name, repo_name, version, created, app_version, description, icon_url, chart_url, source_url, digest, is_latest FROM helm_charts WHERE repo_name = $1 AND name = $2`
getEndpointIDs = `SELECT DISTINCT endpoint FROM helm_charts`
updateChartDigest = `UPDATE helm_charts SET created=$1, is_latest=$2, update_batch=$3 WHERE endpoint=$4 AND name=$5 AND repo_name=$6 AND version=$7`
)
// InitRepositoryProvider - One time init for the given DB Provider
func InitRepositoryProvider(databaseProvider string) {
saveChartVersion = datastore.ModifySQLStatement(saveChartVersion, databaseProvider)
updateChartVersion = datastore.ModifySQLStatement(updateChartVersion, databaseProvider)
updateChartVersion = datastore.ModifySQLStatement(updateChartVersion, databaseProvider)
updateChartDigest = datastore.ModifySQLStatement(updateChartDigest, databaseProvider)
deleteForEndpoint = datastore.ModifySQLStatement(deleteForEndpoint, databaseProvider)
deleteForBatch = datastore.ModifySQLStatement(deleteForBatch, databaseProvider)
renameEndpoint = datastore.ModifySQLStatement(renameEndpoint, databaseProvider)
getLatestCharts = datastore.ModifySQLStatement(getLatestCharts, databaseProvider)
getLatestChart = datastore.ModifySQLStatement(getLatestChart, databaseProvider)
getChartVersion = datastore.ModifySQLStatement(getChartVersion, databaseProvider)
getChartVersions = datastore.ModifySQLStatement(getChartVersions, databaseProvider)
getEndpointIDs = datastore.ModifySQLStatement(getEndpointIDs, databaseProvider)
}
// HelmChartDBStore is a DB-backed Helm Chart repository
type HelmChartDBStore struct {
db *sql.DB
}
// NewHelmChartDBStore will create a new instance of the AnalysisDBStore
func NewHelmChartDBStore(dcp *sql.DB) (ChartStore, error) {
return &HelmChartDBStore{db: dcp}, nil
}
func truncate(in string) string {
return fmt.Sprintf("%.255s", in)
}
// Save a Helm Chart to the database
func (p *HelmChartDBStore) Save(chart ChartStoreRecord, batchID string) error {
sourceURL := ""
if len(chart.Sources) > 0 {
sourceURL = chart.Sources[0]
}
// Get the existing record - if it has the same digest, then no need to store it
record, err := p.GetChart(chart.Repository, chart.Name, chart.Version)
if err == nil && record.Digest == chart.Digest {
log.Debugf("Chart already exists %s/%s-%s with digest %s", chart.Repository, chart.Name, chart.Version, chart.Digest)
_, err := p.db.Exec(updateChartDigest, chart.Created, chart.IsLatest, batchID, chart.EndpointID, chart.Name, chart.Repository, chart.Version)
return err
}
if err == nil {
log.Debugf("Chart already exists %s/%s-%s with different digest %s", chart.Repository, chart.Name, chart.Version, chart.Digest)
// The record already exists, so update it
_, err := p.db.Exec(updateChartVersion, chart.Created, chart.AppVersion, truncate(chart.Description), truncate(chart.IconURL), truncate(chart.ChartURL), truncate(sourceURL), chart.Digest, chart.IsLatest, batchID, chart.EndpointID, chart.Name, chart.Repository, chart.Version)
return err
}
if _, err := p.db.Exec(saveChartVersion, chart.EndpointID, chart.Name, chart.Repository, chart.Version, chart.Created, chart.AppVersion, truncate(chart.Description), truncate(chart.IconURL), truncate(chart.ChartURL), truncate(sourceURL), chart.Digest, chart.IsLatest, batchID); err != nil {
return fmt.Errorf("Unable to save Helm Chart Version: %v", err)
}
return nil
}
// DeleteBatch will remove all chart versions not with the given batch id
func (p *HelmChartDBStore) DeleteBatch(endpointID, chart, batchID string) error {
if _, err := p.db.Exec(deleteForBatch, endpointID, chart, batchID); err != nil {
return fmt.Errorf("Unable to delete Helm Chart Versions for batch ID: %s %v", batchID, err)
}
return nil
}
// DeleteForEndpoint will remove all Helm Charts for a given endpoint guid
func (p *HelmChartDBStore) DeleteForEndpoint(endpointID string) error {
if _, err := p.db.Exec(deleteForEndpoint, endpointID); err != nil {
return fmt.Errorf("Unable to delete Helm Charts for endpoint: %s %v", endpointID, err)
}
return nil
}
// RenameEndpoint will update all charts for a given endpoint to have the new repository name
func (p *HelmChartDBStore) RenameEndpoint(endpointID, name string) error {
if _, err := p.db.Exec(renameEndpoint, name, endpointID); err != nil {
return fmt.Errorf("Unable to rename Helm Chart repository for endpoint: %s %v", endpointID, err)
}
return nil
}
// GetLatestCharts will get only the info for the latest version of each chart
func (p *HelmChartDBStore) GetLatestCharts() ([]*ChartStoreRecord, error) {
rows, err := p.db.Query(getLatestCharts)
if err != nil {
return nil, fmt.Errorf("Unable to retrieve Helm Charts: %v", err)
}
defer rows.Close()
var chartList []*ChartStoreRecord
for rows.Next() {
chart := new(ChartStoreRecord)
sourceURL := ""
err := rows.Scan(&chart.EndpointID, &chart.Name, &chart.Repository, &chart.Version, &chart.Created, &chart.AppVersion, &chart.Description, &chart.IconURL, &chart.ChartURL, &sourceURL, &chart.Digest, &chart.IsLatest)
if err != nil {
return nil, fmt.Errorf("Unable to scan Helm Chart records: %v", err)
}
chart.SemVer = NewSemanticVersion(chart.Version)
addSources(chart, sourceURL)
chartList = append(chartList, chart)
}
if err = rows.Err(); err != nil {
return nil, fmt.Errorf("Unable to list Helm Chart records: %v", err)
}
return chartList, nil
}
// GetChart gets a single helm chart
func (p *HelmChartDBStore) GetChart(repo, name, version string) (*ChartStoreRecord, error) {
var row *sql.Row
chart := new(ChartStoreRecord)
if len(version) == 0 {
row = p.db.QueryRow(getLatestChart, repo, name)
} else {
row = p.db.QueryRow(getChartVersion, repo, name, version)
}
sourceURL := ""
err := row.Scan(&chart.EndpointID, &chart.Name, &chart.Repository, &chart.Version, &chart.Created, &chart.AppVersion, &chart.Description, &chart.IconURL, &chart.ChartURL, &sourceURL, &chart.Digest, &chart.IsLatest)
switch {
case err == sql.ErrNoRows:
return chart, errors.New("No match for that chart")
case err != nil:
return chart, fmt.Errorf("Error trying to find chart record: %v", err)
default:
// do nothing
}
chart.SemVer = NewSemanticVersion(chart.Version)
addSources(chart, sourceURL)
return chart, nil
}
// GetChartVersions will get all of the versions for a given chart
func (p *HelmChartDBStore) GetChartVersions(repo, name string) ([]*ChartStoreRecord, error) {
rows, err := p.db.Query(getChartVersions, repo, name)
if err != nil {
return nil, fmt.Errorf("Unable to retrieve Helm Charts: %v", err)
}
defer rows.Close()
var chartList ChartStoreRecordList
for rows.Next() {
chart := new(ChartStoreRecord)
sourceURL := ""
err := rows.Scan(&chart.EndpointID, &chart.Name, &chart.Repository, &chart.Version, &chart.Created, &chart.AppVersion, &chart.Description, &chart.IconURL, &chart.ChartURL, &sourceURL, &chart.Digest, &chart.IsLatest)
if err != nil {
return nil, fmt.Errorf("Unable to scan Helm Chart records: %v", err)
}
chart.SemVer = NewSemanticVersion(chart.Version)
addSources(chart, sourceURL)
chartList = append(chartList, chart)
}
if err = rows.Err(); err != nil {
return nil, fmt.Errorf("Unable to list Helm Chart records: %v", err)
}
// Sort list by version
sort.Sort(chartList)
return chartList, nil
}
// GetEndpointIDs will get all unique endpoint IDs from the database
func (p *HelmChartDBStore) GetEndpointIDs() ([]string, error) {
rows, err := p.db.Query(getEndpointIDs)
if err != nil {
return nil, fmt.Errorf("Unable to retrieve Endpoint IDs: %v", err)
}
defer rows.Close()
list := make([]string, 0)
for rows.Next() {
var endpoint string
err := rows.Scan(&endpoint)
if err != nil {
return nil, fmt.Errorf("Unable to scan Helm Chart records for endpoints: %v", err)
}
list = append(list, endpoint)
}
if err = rows.Err(); err != nil {
return nil, fmt.Errorf("Unable to list Helm Chart endpoints: %v", err)
}
return list, nil
}
func addSources(record *ChartStoreRecord, sourceURL string) {
record.Sources = make([]string, 0)
if len(sourceURL) > 0 {
record.Sources = append(record.Sources, sourceURL)
}
}