feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
@@ -78,6 +78,7 @@ func (cfgmaps *ConfigMaps) Get(key string) (*rspb.Release, error) {
|
||||
cfgmaps.Log("get: failed to decode data %q: %s", key, err)
|
||||
return nil, err
|
||||
}
|
||||
r.Labels = filterSystemLabels(obj.ObjectMeta.Labels)
|
||||
// return the release object
|
||||
return r, nil
|
||||
}
|
||||
@@ -145,6 +146,7 @@ func (cfgmaps *ConfigMaps) Query(labels map[string]string) ([]*rspb.Release, err
|
||||
cfgmaps.Log("query: failed to decode release: %s", err)
|
||||
continue
|
||||
}
|
||||
rls.Labels = item.ObjectMeta.Labels
|
||||
results = append(results, rls)
|
||||
}
|
||||
return results, nil
|
||||
@@ -157,6 +159,7 @@ func (cfgmaps *ConfigMaps) Create(key string, rls *rspb.Release) error {
|
||||
var lbs labels
|
||||
|
||||
lbs.init()
|
||||
lbs.fromMap(rls.Labels)
|
||||
lbs.set("createdAt", strconv.Itoa(int(time.Now().Unix())))
|
||||
|
||||
// create a new configmap to hold the release
|
||||
@@ -184,6 +187,7 @@ func (cfgmaps *ConfigMaps) Update(key string, rls *rspb.Release) error {
|
||||
var lbs labels
|
||||
|
||||
lbs.init()
|
||||
lbs.fromMap(rls.Labels)
|
||||
lbs.set("modifiedAt", strconv.Itoa(int(time.Now().Unix())))
|
||||
|
||||
// create a new configmap object to hold the release
|
||||
@@ -220,13 +224,12 @@ func (cfgmaps *ConfigMaps) Delete(key string) (rls *rspb.Release, err error) {
|
||||
//
|
||||
// The following labels are used within each configmap:
|
||||
//
|
||||
// "modifiedAt" - timestamp indicating when this configmap was last modified. (set in Update)
|
||||
// "createdAt" - timestamp indicating when this configmap was created. (set in Create)
|
||||
// "version" - version of the release.
|
||||
// "status" - status of the release (see pkg/release/status.go for variants)
|
||||
// "owner" - owner of the configmap, currently "helm".
|
||||
// "name" - name of the release.
|
||||
//
|
||||
// "modifiedAt" - timestamp indicating when this configmap was last modified. (set in Update)
|
||||
// "createdAt" - timestamp indicating when this configmap was created. (set in Create)
|
||||
// "version" - version of the release.
|
||||
// "status" - status of the release (see pkg/release/status.go for variants)
|
||||
// "owner" - owner of the configmap, currently "helm".
|
||||
// "name" - name of the release.
|
||||
func newConfigMapsObject(key string, rls *rspb.Release, lbs labels) (*v1.ConfigMap, error) {
|
||||
const owner = "helm"
|
||||
|
||||
@@ -240,6 +243,9 @@ func newConfigMapsObject(key string, rls *rspb.Release, lbs labels) (*v1.ConfigM
|
||||
lbs.init()
|
||||
}
|
||||
|
||||
// apply custom labels
|
||||
lbs.fromMap(rls.Labels)
|
||||
|
||||
// apply labels
|
||||
lbs.set("name", rls.Name)
|
||||
lbs.set("owner", owner)
|
||||
|
||||
@@ -72,6 +72,7 @@ func (secrets *Secrets) Get(key string) (*rspb.Release, error) {
|
||||
}
|
||||
// found the secret, decode the base64 data string
|
||||
r, err := decodeRelease(string(obj.Data["release"]))
|
||||
r.Labels = filterSystemLabels(obj.ObjectMeta.Labels)
|
||||
return r, errors.Wrapf(err, "get: failed to decode data %q", key)
|
||||
}
|
||||
|
||||
@@ -136,6 +137,7 @@ func (secrets *Secrets) Query(labels map[string]string) ([]*rspb.Release, error)
|
||||
secrets.Log("query: failed to decode release: %s", err)
|
||||
continue
|
||||
}
|
||||
rls.Labels = item.ObjectMeta.Labels
|
||||
results = append(results, rls)
|
||||
}
|
||||
return results, nil
|
||||
@@ -148,6 +150,7 @@ func (secrets *Secrets) Create(key string, rls *rspb.Release) error {
|
||||
var lbs labels
|
||||
|
||||
lbs.init()
|
||||
lbs.fromMap(rls.Labels)
|
||||
lbs.set("createdAt", strconv.Itoa(int(time.Now().Unix())))
|
||||
|
||||
// create a new secret to hold the release
|
||||
@@ -173,6 +176,7 @@ func (secrets *Secrets) Update(key string, rls *rspb.Release) error {
|
||||
var lbs labels
|
||||
|
||||
lbs.init()
|
||||
lbs.fromMap(rls.Labels)
|
||||
lbs.set("modifiedAt", strconv.Itoa(int(time.Now().Unix())))
|
||||
|
||||
// create a new secret object to hold the release
|
||||
@@ -202,13 +206,12 @@ func (secrets *Secrets) Delete(key string) (rls *rspb.Release, err error) {
|
||||
//
|
||||
// The following labels are used within each secret:
|
||||
//
|
||||
// "modifiedAt" - timestamp indicating when this secret was last modified. (set in Update)
|
||||
// "createdAt" - timestamp indicating when this secret was created. (set in Create)
|
||||
// "version" - version of the release.
|
||||
// "status" - status of the release (see pkg/release/status.go for variants)
|
||||
// "owner" - owner of the secret, currently "helm".
|
||||
// "name" - name of the release.
|
||||
//
|
||||
// "modifiedAt" - timestamp indicating when this secret was last modified. (set in Update)
|
||||
// "createdAt" - timestamp indicating when this secret was created. (set in Create)
|
||||
// "version" - version of the release.
|
||||
// "status" - status of the release (see pkg/release/status.go for variants)
|
||||
// "owner" - owner of the secret, currently "helm".
|
||||
// "name" - name of the release.
|
||||
func newSecretsObject(key string, rls *rspb.Release, lbs labels) (*v1.Secret, error) {
|
||||
const owner = "helm"
|
||||
|
||||
@@ -222,6 +225,9 @@ func newSecretsObject(key string, rls *rspb.Release, lbs labels) (*v1.Secret, er
|
||||
lbs.init()
|
||||
}
|
||||
|
||||
// apply custom labels
|
||||
lbs.fromMap(rls.Labels)
|
||||
|
||||
// apply labels
|
||||
lbs.set("name", rls.Name)
|
||||
lbs.set("owner", owner)
|
||||
|
||||
215
vendor/helm.sh/helm/v3/pkg/storage/driver/sql.go
vendored
215
vendor/helm.sh/helm/v3/pkg/storage/driver/sql.go
vendored
@@ -19,6 +19,7 @@ package driver // import "helm.sh/helm/v3/pkg/storage/driver"
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
@@ -49,6 +50,7 @@ const postgreSQLDialect = "postgres"
|
||||
const SQLDriverName = "SQL"
|
||||
|
||||
const sqlReleaseTableName = "releases_v1"
|
||||
const sqlCustomLabelsTableName = "custom_labels_v1"
|
||||
|
||||
const (
|
||||
sqlReleaseTableKeyColumn = "key"
|
||||
@@ -61,6 +63,17 @@ const (
|
||||
sqlReleaseTableOwnerColumn = "owner"
|
||||
sqlReleaseTableCreatedAtColumn = "createdAt"
|
||||
sqlReleaseTableModifiedAtColumn = "modifiedAt"
|
||||
|
||||
sqlCustomLabelsTableReleaseKeyColumn = "releaseKey"
|
||||
sqlCustomLabelsTableReleaseNamespaceColumn = "releaseNamespace"
|
||||
sqlCustomLabelsTableKeyColumn = "key"
|
||||
sqlCustomLabelsTableValueColumn = "value"
|
||||
)
|
||||
|
||||
// Following limits based on k8s labels limits - https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set
|
||||
const (
|
||||
sqlCustomLabelsTableKeyMaxLenght = 253 + 1 + 63
|
||||
sqlCustomLabelsTableValueMaxLenght = 63
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -82,8 +95,42 @@ func (s *SQL) Name() string {
|
||||
return SQLDriverName
|
||||
}
|
||||
|
||||
// Check if all migrations al
|
||||
func (s *SQL) checkAlreadyApplied(migrations []*migrate.Migration) bool {
|
||||
// make map (set) of ids for fast search
|
||||
migrationsIds := make(map[string]struct{})
|
||||
for _, migration := range migrations {
|
||||
migrationsIds[migration.Id] = struct{}{}
|
||||
}
|
||||
|
||||
// get list of applied migrations
|
||||
migrate.SetDisableCreateTable(true)
|
||||
records, err := migrate.GetMigrationRecords(s.db.DB, postgreSQLDialect)
|
||||
migrate.SetDisableCreateTable(false)
|
||||
if err != nil {
|
||||
s.Log("checkAlreadyApplied: failed to get migration records: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
if _, ok := migrationsIds[record.Id]; ok {
|
||||
s.Log("checkAlreadyApplied: found previous migration (Id: %v) applied at %v", record.Id, record.AppliedAt)
|
||||
delete(migrationsIds, record.Id)
|
||||
}
|
||||
}
|
||||
|
||||
// check if all migrations appliyed
|
||||
if len(migrationsIds) != 0 {
|
||||
for id := range migrationsIds {
|
||||
s.Log("checkAlreadyApplied: find unapplied migration (id: %v)", id)
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *SQL) ensureDBSetup() error {
|
||||
// Populate the database with the relations we need if they don't exist yet
|
||||
|
||||
migrations := &migrate.MemoryMigrationSource{
|
||||
Migrations: []*migrate.Migration{
|
||||
{
|
||||
@@ -91,7 +138,7 @@ func (s *SQL) ensureDBSetup() error {
|
||||
Up: []string{
|
||||
fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
%s VARCHAR(67),
|
||||
%s VARCHAR(90),
|
||||
%s VARCHAR(64) NOT NULL,
|
||||
%s TEXT NOT NULL,
|
||||
%s VARCHAR(64) NOT NULL,
|
||||
@@ -109,9 +156,9 @@ func (s *SQL) ensureDBSetup() error {
|
||||
CREATE INDEX ON %s (%s);
|
||||
CREATE INDEX ON %s (%s);
|
||||
CREATE INDEX ON %s (%s);
|
||||
|
||||
|
||||
GRANT ALL ON %s TO PUBLIC;
|
||||
|
||||
|
||||
ALTER TABLE %s ENABLE ROW LEVEL SECURITY;
|
||||
`,
|
||||
sqlReleaseTableName,
|
||||
@@ -150,9 +197,50 @@ func (s *SQL) ensureDBSetup() error {
|
||||
`, sqlReleaseTableName),
|
||||
},
|
||||
},
|
||||
{
|
||||
Id: "custom_labels",
|
||||
Up: []string{
|
||||
fmt.Sprintf(`
|
||||
CREATE TABLE %s (
|
||||
%s VARCHAR(64),
|
||||
%s VARCHAR(67),
|
||||
%s VARCHAR(%d),
|
||||
%s VARCHAR(%d)
|
||||
);
|
||||
CREATE INDEX ON %s (%s, %s);
|
||||
|
||||
GRANT ALL ON %s TO PUBLIC;
|
||||
ALTER TABLE %s ENABLE ROW LEVEL SECURITY;
|
||||
`,
|
||||
sqlCustomLabelsTableName,
|
||||
sqlCustomLabelsTableReleaseKeyColumn,
|
||||
sqlCustomLabelsTableReleaseNamespaceColumn,
|
||||
sqlCustomLabelsTableKeyColumn,
|
||||
sqlCustomLabelsTableKeyMaxLenght,
|
||||
sqlCustomLabelsTableValueColumn,
|
||||
sqlCustomLabelsTableValueMaxLenght,
|
||||
sqlCustomLabelsTableName,
|
||||
sqlCustomLabelsTableReleaseKeyColumn,
|
||||
sqlCustomLabelsTableReleaseNamespaceColumn,
|
||||
sqlCustomLabelsTableName,
|
||||
sqlCustomLabelsTableName,
|
||||
),
|
||||
},
|
||||
Down: []string{
|
||||
fmt.Sprintf(`
|
||||
DELETE TABLE %s;
|
||||
`, sqlCustomLabelsTableName),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Check that init migration already applied
|
||||
if s.checkAlreadyApplied(migrations.Migrations) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Populate the database with the relations we need if they don't exist yet
|
||||
_, err := migrate.Exec(s.db.DB, postgreSQLDialect, migrations, migrate.Up)
|
||||
return err
|
||||
}
|
||||
@@ -180,6 +268,13 @@ type SQLReleaseWrapper struct {
|
||||
ModifiedAt int `db:"modifiedAt"`
|
||||
}
|
||||
|
||||
type SQLReleaseCustomLabelWrapper struct {
|
||||
ReleaseKey string `db:"release_key"`
|
||||
ReleaseNamespace string `db:"release_namespace"`
|
||||
Key string `db:"key"`
|
||||
Value string `db:"value"`
|
||||
}
|
||||
|
||||
// NewSQL initializes a new sql driver.
|
||||
func NewSQL(connectionString string, logger func(string, ...interface{}), namespace string) (*SQL, error) {
|
||||
db, err := sqlx.Connect(postgreSQLDialect, connectionString)
|
||||
@@ -230,13 +325,18 @@ func (s *SQL) Get(key string) (*rspb.Release, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if release.Labels, err = s.getReleaseCustomLabels(key, s.namespace); err != nil {
|
||||
s.Log("failed to get release %s/%s custom labels: %v", s.namespace, key, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return release, nil
|
||||
}
|
||||
|
||||
// List returns the list of all releases such that filter(release) == true
|
||||
func (s *SQL) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error) {
|
||||
sb := s.statementBuilder.
|
||||
Select(sqlReleaseTableBodyColumn).
|
||||
Select(sqlReleaseTableKeyColumn, sqlReleaseTableNamespaceColumn, sqlReleaseTableBodyColumn).
|
||||
From(sqlReleaseTableName).
|
||||
Where(sq.Eq{sqlReleaseTableOwnerColumn: sqlReleaseDefaultOwner})
|
||||
|
||||
@@ -264,6 +364,15 @@ func (s *SQL) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error) {
|
||||
s.Log("list: failed to decode release: %v: %v", record, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if release.Labels, err = s.getReleaseCustomLabels(record.Key, record.Namespace); err != nil {
|
||||
s.Log("failed to get release %s/%s custom labels: %v", record.Namespace, record.Key, err)
|
||||
return nil, err
|
||||
}
|
||||
for k, v := range getReleaseSystemLabels(release) {
|
||||
release.Labels[k] = v
|
||||
}
|
||||
|
||||
if filter(release) {
|
||||
releases = append(releases, release)
|
||||
}
|
||||
@@ -275,7 +384,7 @@ func (s *SQL) List(filter func(*rspb.Release) bool) ([]*rspb.Release, error) {
|
||||
// Query returns the set of releases that match the provided set of labels.
|
||||
func (s *SQL) Query(labels map[string]string) ([]*rspb.Release, error) {
|
||||
sb := s.statementBuilder.
|
||||
Select(sqlReleaseTableBodyColumn).
|
||||
Select(sqlReleaseTableKeyColumn, sqlReleaseTableNamespaceColumn, sqlReleaseTableBodyColumn).
|
||||
From(sqlReleaseTableName)
|
||||
|
||||
keys := make([]string, 0, len(labels))
|
||||
@@ -321,6 +430,12 @@ func (s *SQL) Query(labels map[string]string) ([]*rspb.Release, error) {
|
||||
s.Log("list: failed to decode release: %v: %v", record, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if release.Labels, err = s.getReleaseCustomLabels(record.Key, record.Namespace); err != nil {
|
||||
s.Log("failed to get release %s/%s custom labels: %v", record.Namespace, record.Key, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
releases = append(releases, release)
|
||||
}
|
||||
|
||||
@@ -403,6 +518,36 @@ func (s *SQL) Create(key string, rls *rspb.Release) error {
|
||||
s.Log("failed to store release %s in SQL database: %v", key, err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Filtering labels before insert cause in SQL storage driver system releases are stored in separate columns of release table
|
||||
for k, v := range filterSystemLabels(rls.Labels) {
|
||||
insertLabelsQuery, args, err := s.statementBuilder.
|
||||
Insert(sqlCustomLabelsTableName).
|
||||
Columns(
|
||||
sqlCustomLabelsTableReleaseKeyColumn,
|
||||
sqlCustomLabelsTableReleaseNamespaceColumn,
|
||||
sqlCustomLabelsTableKeyColumn,
|
||||
sqlCustomLabelsTableValueColumn,
|
||||
).
|
||||
Values(
|
||||
key,
|
||||
namespace,
|
||||
k,
|
||||
v,
|
||||
).ToSql()
|
||||
|
||||
if err != nil {
|
||||
defer transaction.Rollback()
|
||||
s.Log("failed to build insert query: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := transaction.Exec(insertLabelsQuery, args...); err != nil {
|
||||
defer transaction.Rollback()
|
||||
s.Log("failed to write Labels: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer transaction.Commit()
|
||||
|
||||
return nil
|
||||
@@ -487,10 +632,66 @@ func (s *SQL) Delete(key string) (*rspb.Release, error) {
|
||||
Where(sq.Eq{sqlReleaseTableNamespaceColumn: s.namespace}).
|
||||
ToSql()
|
||||
if err != nil {
|
||||
s.Log("failed to build select query: %v", err)
|
||||
s.Log("failed to build delete query: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = transaction.Exec(deleteQuery, args...)
|
||||
if err != nil {
|
||||
s.Log("failed perform delete query: %v", err)
|
||||
return release, err
|
||||
}
|
||||
|
||||
if release.Labels, err = s.getReleaseCustomLabels(key, s.namespace); err != nil {
|
||||
s.Log("failed to get release %s/%s custom labels: %v", s.namespace, key, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deleteCustomLabelsQuery, args, err := s.statementBuilder.
|
||||
Delete(sqlCustomLabelsTableName).
|
||||
Where(sq.Eq{sqlCustomLabelsTableReleaseKeyColumn: key}).
|
||||
Where(sq.Eq{sqlCustomLabelsTableReleaseNamespaceColumn: s.namespace}).
|
||||
ToSql()
|
||||
|
||||
if err != nil {
|
||||
s.Log("failed to build delete Labels query: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
_, err = transaction.Exec(deleteCustomLabelsQuery, args...)
|
||||
return release, err
|
||||
}
|
||||
|
||||
// Get release custom labels from database
|
||||
func (s *SQL) getReleaseCustomLabels(key string, _ string) (map[string]string, error) {
|
||||
query, args, err := s.statementBuilder.
|
||||
Select(sqlCustomLabelsTableKeyColumn, sqlCustomLabelsTableValueColumn).
|
||||
From(sqlCustomLabelsTableName).
|
||||
Where(sq.Eq{sqlCustomLabelsTableReleaseKeyColumn: key,
|
||||
sqlCustomLabelsTableReleaseNamespaceColumn: s.namespace}).
|
||||
ToSql()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var labelsList = []SQLReleaseCustomLabelWrapper{}
|
||||
if err := s.db.Select(&labelsList, query, args...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
labelsMap := make(map[string]string)
|
||||
for _, i := range labelsList {
|
||||
labelsMap[i.Key] = i.Value
|
||||
}
|
||||
|
||||
return filterSystemLabels(labelsMap), nil
|
||||
}
|
||||
|
||||
// Rebuild system labels from release object
|
||||
func getReleaseSystemLabels(rls *rspb.Release) map[string]string {
|
||||
return map[string]string{
|
||||
"name": rls.Name,
|
||||
"owner": sqlReleaseDefaultOwner,
|
||||
"status": rls.Info.Status.String(),
|
||||
"version": strconv.Itoa(rls.Version),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
|
||||
rspb "helm.sh/helm/v3/pkg/release"
|
||||
)
|
||||
@@ -30,6 +30,8 @@ var b64 = base64.StdEncoding
|
||||
|
||||
var magicGzip = []byte{0x1f, 0x8b, 0x08}
|
||||
|
||||
var systemLabels = []string{"name", "owner", "status", "version", "createdAt", "modifiedAt"}
|
||||
|
||||
// encodeRelease encodes a release returning a base64 encoded
|
||||
// gzipped string representation, or error.
|
||||
func encodeRelease(rls *rspb.Release) (string, error) {
|
||||
@@ -69,7 +71,7 @@ func decodeRelease(data string) (*rspb.Release, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
b2, err := ioutil.ReadAll(r)
|
||||
b2, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -83,3 +85,38 @@ func decodeRelease(data string) (*rspb.Release, error) {
|
||||
}
|
||||
return &rls, nil
|
||||
}
|
||||
|
||||
// Checks if label is system
|
||||
func isSystemLabel(key string) bool {
|
||||
for _, v := range GetSystemLabels() {
|
||||
if key == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Removes system labels from labels map
|
||||
func filterSystemLabels(lbs map[string]string) map[string]string {
|
||||
result := make(map[string]string)
|
||||
for k, v := range lbs {
|
||||
if !isSystemLabel(k) {
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Checks if labels array contains system labels
|
||||
func ContainsSystemLabels(lbs map[string]string) bool {
|
||||
for k := range lbs {
|
||||
if isSystemLabel(k) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetSystemLabels() []string {
|
||||
return systemLabels
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user