From 65e17352ef1244b3c8ea55f0430b23aec02ecf8d Mon Sep 17 00:00:00 2001 From: liamfallon Date: Thu, 9 Jan 2025 16:24:16 +0000 Subject: [PATCH] Added handling for resources --- .../tutorials/database-cache/porch-db.sql | 46 +++--- pkg/cache/dbcache/dbpackage.go | 27 +++- pkg/cache/dbcache/dbpackagerevision.go | 35 +++- .../dbcache/dbpackagerevisionresourcessql.go | 149 ++++++++++++++++++ pkg/cache/dbcache/dbpackagerevisionsql.go | 120 ++++++++------ pkg/cache/dbcache/dbpackagesql.go | 41 +++-- pkg/cache/dbcache/dbrepository.go | 25 ++- pkg/cache/dbcache/dbrepositorysql.go | 8 +- pkg/util/util.go | 15 +- 9 files changed, 359 insertions(+), 107 deletions(-) create mode 100644 pkg/cache/dbcache/dbpackagerevisionresourcessql.go diff --git a/examples/tutorials/database-cache/porch-db.sql b/examples/tutorials/database-cache/porch-db.sql index f92727c2..898f3118 100644 --- a/examples/tutorials/database-cache/porch-db.sql +++ b/examples/tutorials/database-cache/porch-db.sql @@ -1,69 +1,67 @@ +DROP TABLE IF EXISTS resources; DROP TABLE IF EXISTS package_revisions; DROP TABLE IF EXISTS packages; DROP TABLE IF EXISTS repositories; -DROP TABLE IF EXISTS resources; DROP TYPE IF EXISTS package_rev_lifecycle; CREATE TABLE IF NOT EXISTS repositories ( - namespace TEXT NOT NULL, + name_space TEXT NOT NULL, repo_name TEXT NOT NULL, - meta JSONB NOT NULL, - spec JSONB NOT NULL, + meta TEXT NOT NULL, + spec TEXT NOT NULL, updated TIMESTAMPTZ, updatedby TEXT NOT NULL, deployment BOOLEAN, - PRIMARY KEY (namespace, repo_name) + PRIMARY KEY (name_space, repo_name) ); CREATE TABLE IF NOT EXISTS packages ( - namespace TEXT NOT NULL, + name_space TEXT NOT NULL, repo_name TEXT NOT NULL, package_name TEXT NOT NULL, - meta JSONB NOT NULL, - spec JSONB NOT NULL, + meta TEXT NOT NULL, + spec TEXT NOT NULL, updated TIMESTAMPTZ NOT NULL, updatedby TEXT NOT NULL, - PRIMARY KEY (namespace, repo_name, package_name), + PRIMARY KEY (name_space, repo_name, package_name), CONSTRAINT fk_repository - FOREIGN KEY (namespace, repo_name) - REFERENCES repositories (namespace, repo_name) + FOREIGN KEY (name_space, repo_name) + REFERENCES repositories (name_space, repo_name) ON DELETE CASCADE ); CREATE TYPE package_rev_lifecycle AS ENUM ('Draft', 'Proposed', 'Published', 'DeletionProposed'); CREATE TABLE IF NOT EXISTS package_revisions ( - namespace TEXT NOT NULL, + name_space TEXT NOT NULL, repo_name TEXT NOT NULL, package_name TEXT NOT NULL, package_rev TEXT NOT NULL, workspace_name TEXT NOT NULL, - meta JSONB NOT NULL, - spec JSONB NOT NULL, + meta TEXT NOT NULL, + spec TEXT NOT NULL, updated TIMESTAMPTZ NOT NULL, updatedby TEXT NOT NULL, lifecycle package_rev_lifecycle NOT NULL, - PRIMARY KEY (namespace, repo_name, package_name, package_rev), + PRIMARY KEY (name_space, repo_name, package_name, package_rev, workspace_name), CONSTRAINT fk_package - FOREIGN KEY (namespace, repo_name, package_name) - REFERENCES packages (namespace, repo_name, package_name) + FOREIGN KEY (name_space, repo_name, package_name) + REFERENCES packages (name_space, repo_name, package_name) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS resources ( - namespace TEXT NOT NULL, + name_space TEXT NOT NULL, repo_name TEXT NOT NULL, package_name TEXT NOT NULL, package_rev TEXT NOT NULL, workspace_name TEXT NOT NULL, resource_key TEXT NOT NULL, - resource_value JSONB NOT NULL, - lifecycle package_rev_lifecycle NOT NULL, - resources BYTEA, - PRIMARY KEY (namespace, repo_name, package_name, package_rev), + resource_value TEXT NOT NULL, + PRIMARY KEY (name_space, repo_name, package_name, package_rev, workspace_name, resource_key), CONSTRAINT fk_package - FOREIGN KEY (namespace, repo_name, package_name) - REFERENCES packages (namespace, repo_name, package_name) + FOREIGN KEY (name_space, repo_name, package_name, package_rev, workspace_name) + REFERENCES package_revisions (name_space, repo_name, package_name, package_rev, workspace_name) ON DELETE CASCADE ); diff --git a/pkg/cache/dbcache/dbpackage.go b/pkg/cache/dbcache/dbpackage.go index daaa896b..f3013acf 100644 --- a/pkg/cache/dbcache/dbpackage.go +++ b/pkg/cache/dbcache/dbpackage.go @@ -17,6 +17,7 @@ package dbcache import ( "context" "database/sql" + "encoding/json" "time" "github.com/nephio-project/porch/api/porch/v1alpha1" @@ -51,7 +52,7 @@ func (p *dbPackage) Key() repository.PackageKey { return p.pkgKey } -func (p *dbPackage) createPackage() (*dbPackage, error) { +func (p *dbPackage) savePackage() (*dbPackage, error) { _, err := pkgReadFromDB(p.Key()) if err == nil { return p, pkgUpdateDB(p) @@ -99,8 +100,8 @@ func (p *dbPackage) GetPackage() *v1alpha1.PorchPackage { } } -func (p *dbPackage) createPackageRevision(d *dbPackageRevision) (*dbPackageRevision, error) { - return d.createPackageRevision() +func (p *dbPackage) savePackageRevision(d *dbPackageRevision) (*dbPackageRevision, error) { + return d.savePackageRevision() } func (p *dbPackage) DeletePackageRevision(ctx context.Context, old repository.PackageRevision) error { @@ -138,3 +139,23 @@ func (p *dbPackage) Delete() error { return pkgDeleteFromDB(p.Key()) } + +func (p *dbPackage) metaAsJson() string { + jsonMeta, _ := json.Marshal(p.meta) + return string(jsonMeta) +} + +func (p *dbPackage) setMetaFromJson(jsonMeta string) { + p.meta = metav1.ObjectMeta{} + json.Unmarshal([]byte(jsonMeta), p.meta) +} + +func (p *dbPackage) specAsJson() string { + jsonSpec, _ := json.Marshal(p.spec) + return string(jsonSpec) +} + +func (p *dbPackage) setSpecFromJson(jsonSpec string) { + p.spec = v1alpha1.PackageSpec{} + json.Unmarshal([]byte(jsonSpec), p.spec) +} diff --git a/pkg/cache/dbcache/dbpackagerevision.go b/pkg/cache/dbcache/dbpackagerevision.go index 43250925..4e40a742 100644 --- a/pkg/cache/dbcache/dbpackagerevision.go +++ b/pkg/cache/dbcache/dbpackagerevision.go @@ -17,6 +17,7 @@ package dbcache import ( "context" "database/sql" + "encoding/json" "errors" "fmt" "strings" @@ -61,7 +62,7 @@ func (pr *dbPackageRevision) Key() repository.PackageRevisionKey { return pr.pkgRevKey } -func (pr *dbPackageRevision) createPackageRevision() (*dbPackageRevision, error) { +func (pr *dbPackageRevision) savePackageRevision() (*dbPackageRevision, error) { _, err := pkgRevReadFromDB(pr.Key()) if err == nil { return pr, pkgRevUpdateDB(pr) @@ -191,13 +192,13 @@ func (pr *dbPackageRevision) GetUpstreamLock(context.Context) (kptfile.Upstream, return kptfile.Upstream{}, kptfile.UpstreamLock{}, nil } -func (p *dbPackageRevision) ToMainPackageRevision() repository.PackageRevision { +func (pr *dbPackageRevision) ToMainPackageRevision() repository.PackageRevision { return &dbPackageRevision{ - pkgRevKey: p.pkgRevKey, - updated: p.updated, - updatedBy: p.updatedBy, - lifecycle: p.lifecycle, - resources: p.resources, + pkgRevKey: pr.pkgRevKey, + updated: pr.updated, + updatedBy: pr.updatedBy, + lifecycle: pr.lifecycle, + resources: pr.resources, } } @@ -257,3 +258,23 @@ func (pr *dbPackageRevision) UpdateResources(ctx context.Context, new *v1alpha1. func (pr *dbPackageRevision) GetName() string { return pr.pkgRevKey.Package } + +func (pr *dbPackageRevision) metaAsJson() string { + jsonMeta, _ := json.Marshal(pr.meta) + return string(jsonMeta) +} + +func (pr *dbPackageRevision) setMetaFromJson(jsonMeta string) { + pr.meta = metav1.ObjectMeta{} + json.Unmarshal([]byte(jsonMeta), pr.meta) +} + +func (pr *dbPackageRevision) specAsJson() string { + jsonSpec, _ := json.Marshal(pr.spec) + return string(jsonSpec) +} + +func (pr *dbPackageRevision) setSpecFromJson(jsonSpec string) { + pr.spec = v1alpha1.PackageRevisionSpec{} + json.Unmarshal([]byte(jsonSpec), pr.spec) +} diff --git a/pkg/cache/dbcache/dbpackagerevisionresourcessql.go b/pkg/cache/dbcache/dbpackagerevisionresourcessql.go new file mode 100644 index 00000000..2cc03d00 --- /dev/null +++ b/pkg/cache/dbcache/dbpackagerevisionresourcessql.go @@ -0,0 +1,149 @@ +// Copyright 2024 The Nephio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dbcache + +import ( + "database/sql" + + "github.com/nephio-project/porch/pkg/repository" + "k8s.io/klog/v2" +) + +func pkgRevResourceReadFromDB(prk repository.PackageRevisionKey, resKey string) (string, string, error) { + klog.Infof("pkgRevResourceReadFromDB: reading package revision resource %q:%s", prk, resKey) + + sqlStatement := `SELECT resource_value FROM resources + WHERE name_space=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4 AND workspace_name=$5 AND key=$6` + + var resVal string + + err := GetDBConnection().db.QueryRow( + sqlStatement, prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName).Scan( + &resVal) + + if err != nil { + if err == sql.ErrNoRows { + klog.Infof("pkgRevResourceReadFromDB: package revision resource not found in db %q:%s", prk, resKey) + } else { + klog.Infof("pkgRevResourceReadFromDB: reading package revision resource %q:%s returned err: %q", prk, resKey, err) + } + return resKey, "", err + } + + klog.Infof("pkgRevResourceReadFromDB: reading package succeeded %q:%s", prk, resKey) + + return resKey, resVal, err +} + +func pkgRevResourcesReadFromDB(prk repository.PackageRevisionKey) (map[string]string, error) { + sqlStatement := `SELECT * FROM resources WHERE name_space=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4 AND workspace_name=$5` + + resources := make(map[string]string) + + klog.Infof("pkgRevResourcesReadFromDB: running query [%q] on %q", sqlStatement, prk) + + rows, err := GetDBConnection().db.Query(sqlStatement, prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName) + if err != nil { + klog.Infof("pkgRevResourcesReadFromDB: query failed for %q: %q", prk, err) + return nil, err + } + + klog.Infof("pkgRevResourcesReadFromDB: query succeeded for %q", prk) + + defer rows.Close() + + for rows.Next() { + var resKey, resVal string + + rows.Scan( + &resKey, + &resVal) + + resources[resKey] = resVal + } + + return resources, nil +} + +func pkgRevResourcesWriteToDB(pr *dbPackageRevision) error { + klog.Infof("pkgRevResourcesWriteToDB: writing package revision resources for %q", pr.Key()) + + for k, v := range pr.resources { + if err := pkgRevResourceWriteToDB(pr, k, v); err != nil { + return err + } + } + + klog.Infof("pkgRevResourcesWriteToDB: succeeded, row created") + return nil +} + +func pkgRevResourceWriteToDB(pr *dbPackageRevision, resKey string, resVal string) error { + klog.Infof("pkgRevResourceWriteToDB: writing package revision resource %q:%s", pr.Key(), resKey) + + sqlStatement := ` + INSERT INTO resources (name_space, repo_name, package_name, package_rev, workspace_name, resource_key, resource_value) + VALUES ($1, $2, $3, $4, $5, $6, $7) + ON CONFLICT (name_space, repo_name, package_name, package_rev, workspace_name, resource_key) + DO UPDATE SET resource_value = EXCLUDED.resource_value` + + klog.Infof("pkgRevResourceWriteToDB: running query [%q] on repository (%#v)", sqlStatement, pr) + + prk := pr.Key() + if returnedVal := GetDBConnection().db.QueryRow( + sqlStatement, + prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName, + resKey, resVal); returnedVal.Err() == nil { + klog.Infof("pkgRevResourceWriteToDB: query succeeded, row created") + return nil + } else { + klog.Infof("pkgRevResourceWriteToDB: query failed %q", returnedVal.Err()) + return returnedVal.Err() + } +} + +func pkgRevResourcesDeleteFromDB(prk repository.PackageRevisionKey) error { + klog.Infof("pkgRevResourcesDeleteFromDB: deleting package revision %q", prk) + + sqlStatement := `DELETE FROM resources WHERE name_space=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4 AND workspace_name=$5` + + returnedVal := GetDBConnection().db.QueryRow(sqlStatement, + prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName) + + if returnedVal.Err() == nil { + klog.Infof("pkgRevResourcesDeleteFromDB: deleted package revision %q", prk) + } else { + klog.Infof("pkgRevResourcesDeleteFromDB: deletion of package revision %q failed: %q", prk, returnedVal.Err()) + } + + return returnedVal.Err() +} + +func pkgRevResourceDeleteFromDB(prk repository.PackageRevisionKey, resKey string) error { + klog.Infof("pkgRevResourceDeleteFromDB: deleting package revision %q", prk) + + sqlStatement := `DELETE FROM resources WHERE name_space=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4 AND workspace_name=$5 AND presource_key=$6` + + returnedVal := GetDBConnection().db.QueryRow(sqlStatement, + prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName, resKey) + + if returnedVal.Err() == nil { + klog.Infof("pkgRevResourceDeleteFromDB: deleted package revision %q", prk) + } else { + klog.Infof("pkgRevResourceDeleteFromDB: deletion of package revision %q failed: %q", prk, returnedVal.Err()) + } + + return returnedVal.Err() +} diff --git a/pkg/cache/dbcache/dbpackagerevisionsql.go b/pkg/cache/dbcache/dbpackagerevisionsql.go index 87bac06b..99380fb2 100644 --- a/pkg/cache/dbcache/dbpackagerevisionsql.go +++ b/pkg/cache/dbcache/dbpackagerevisionsql.go @@ -25,44 +25,49 @@ func pkgRevReadFromDB(prk repository.PackageRevisionKey) (dbPackageRevision, err klog.Infof("pkgRevReadFromDB: reading package revision %q", prk) sqlStatement := `SELECT * FROM package_revisions - WHERE namespace=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4` + WHERE name_space=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4 AND workspace_name=$5` - var dbPkgRev dbPackageRevision - var rawResources []byte + var pkgRev dbPackageRevision + var metaAsJson, specAsJson string err := GetDBConnection().db.QueryRow( - sqlStatement, prk.Namespace, prk.Repository, prk.Package, prk.Revision).Scan( - &dbPkgRev.pkgRevKey.Namespace, - &dbPkgRev.pkgRevKey.Repository, - &dbPkgRev.pkgRevKey.Package, - &dbPkgRev.pkgRevKey.Revision, - &dbPkgRev.pkgRevKey.WorkspaceName, - &dbPkgRev.updated, - &dbPkgRev.updatedBy, - &dbPkgRev.lifecycle, - &rawResources) + sqlStatement, prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName).Scan( + &pkgRev.pkgRevKey.Namespace, + &pkgRev.pkgRevKey.Repository, + &pkgRev.pkgRevKey.Package, + &pkgRev.pkgRevKey.Revision, + &pkgRev.pkgRevKey.WorkspaceName, + &metaAsJson, + &specAsJson, + &pkgRev.updated, + &pkgRev.updatedBy, + &pkgRev.lifecycle) if err != nil { if err == sql.ErrNoRows { - klog.Infof("pkgRevReadFromDB: package not found in db %q", prk) + klog.Infof("pkgRevReadFromDB: package revision not found in db %q", prk) } else { klog.Infof("pkgRevReadFromDB: reading package revision %q returned err: %q", prk, err) } - return dbPkgRev, err + return pkgRev, err } - klog.Infof("pkgRevReadFromDB: reading package succeeded %q", prk) - - dbPkgRev.resources, err = GetDBConnection().encoder.DecodePackage(rawResources) + pkgRev.resources, err = pkgRevResourcesReadFromDB(prk) if err != nil { - klog.Infof("pkgRevReadFromDB: reading package revision resources %q returned err: %q", prk, err) + klog.Infof("pkgRevReadFromDB: reading package revision %q resources returned err: %q", prk, err) + return pkgRev, err } - return dbPkgRev, err + klog.Infof("pkgRevReadFromDB: reading package succeeded %q", prk) + + pkgRev.setMetaFromJson(metaAsJson) + pkgRev.setSpecFromJson(specAsJson) + + return pkgRev, err } func pkgRevReadPRsFromDB(pk repository.PackageKey) ([]*dbPackageRevision, error) { - sqlStatement := `SELECT * FROM package_revisions WHERE namespace=$1 AND repo_name=$2 AND package_name=$3` + sqlStatement := `SELECT * FROM package_revisions WHERE name_space=$1 AND repo_name=$2 AND package_name=$3` var dbPkgRevs []*dbPackageRevision @@ -80,7 +85,7 @@ func pkgRevReadPRsFromDB(pk repository.PackageKey) ([]*dbPackageRevision, error) for rows.Next() { var pkgRev dbPackageRevision - var rawResources []byte + var metaAsJson, specAsJson string rows.Scan( &pkgRev.pkgRevKey.Namespace, @@ -88,37 +93,39 @@ func pkgRevReadPRsFromDB(pk repository.PackageKey) ([]*dbPackageRevision, error) &pkgRev.pkgRevKey.Package, &pkgRev.pkgRevKey.Revision, &pkgRev.pkgRevKey.WorkspaceName, + &metaAsJson, + &specAsJson, &pkgRev.updated, &pkgRev.updatedBy, - &pkgRev.lifecycle, - &rawResources) + &pkgRev.lifecycle) - pkgRev.resources, err = GetDBConnection().encoder.DecodePackage(rawResources) + pkgRev.resources, err = pkgRevResourcesReadFromDB(pkgRev.pkgRevKey) if err != nil { - klog.Infof("pkgRevReadFromDB: reading package revision resources %q returned err: %q", pkgRev.Key(), err) + klog.Infof("pkgRevReadFromDB: reading package revision %q resources returned err: %q", pkgRev.pkgRevKey, err) + return nil, err } + klog.Infof("pkgRevReadFromDB: reading package succeeded %q", pkgRev.pkgRevKey) + + pkgRev.setMetaFromJson(metaAsJson) + pkgRev.setSpecFromJson(specAsJson) + dbPkgRevs = append(dbPkgRevs, &pkgRev) } return dbPkgRevs, nil } -func pkgRevReadLatestPRFromDB(pk repository.PackageKey) *dbPackageRevision { +func pkgRevReadLatestPRFromDB(_ repository.PackageKey) *dbPackageRevision { return nil } func pkgRevWriteToDB(pr *dbPackageRevision) error { klog.Infof("pkgRevWriteToDB: writing package revision %q", pr.Key()) - rawResources, err := GetDBConnection().encoder.EncodePackage(pr.resources) - if err != nil { - return err - } - sqlStatement := ` - INSERT INTO package_revisions (namespace, repo_name, package_name, package_rev, workspace_name, updated, updatedby, lifecycle, resources) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)` + INSERT INTO package_revisions (name_space, repo_name, package_name, package_rev, workspace_name, meta, spec, updated, updatedby, lifecycle) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)` klog.Infof("pkgRevWriteToDB: running query [%q] on repository (%#v)", sqlStatement, pr) @@ -126,50 +133,65 @@ func pkgRevWriteToDB(pr *dbPackageRevision) error { if returnedVal := GetDBConnection().db.QueryRow( sqlStatement, prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName, - pr.updated, pr.updatedBy, pr.lifecycle, rawResources); returnedVal.Err() == nil { + pr.metaAsJson(), pr.specAsJson(), pr.updated, pr.updatedBy, pr.lifecycle); returnedVal.Err() == nil { klog.Infof("pkgRevWriteToDB: query succeeded, row created") - return nil } else { klog.Infof("pkgRevWriteToDB: query failed %q", returnedVal.Err()) return returnedVal.Err() } + + if err := pkgRevResourcesWriteToDB(pr); err == nil { + klog.Infof("pkgRevWriteToDB: resources written to DB") + return nil + } else { + klog.Infof("pkgRevWriteToDB: resource write to DB failed: %q", err) + return err + } } func pkgRevUpdateDB(pr *dbPackageRevision) error { - klog.Infof("pkgRevUpdateDB: updating package revision %q", pr.Key()) - rawResources, err := GetDBConnection().encoder.EncodePackage(pr.resources) - if err != nil { - return err - } - sqlStatement := ` - UPDATE package_revisions SET updated=$5, updatedby=$6, lifecycle=$7, resources=$8 - WHERE namespace=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4` + UPDATE package_revisions SET meta=$6, spec=$7, updated=$8, updatedby=$9, lifecycle=$10 + WHERE name_space=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4 AND workspace_name=$5` klog.Infof("pkgRevUpdateDB: running query [%q] on repository (%#v)", sqlStatement, pr) prk := pr.Key() if returnedVal := GetDBConnection().db.QueryRow( sqlStatement, - prk.Namespace, prk.Repository, prk.Package, prk.Revision, - pr.updated, pr.updatedBy, pr.lifecycle, rawResources); returnedVal.Err() == nil { + prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName, + pr.metaAsJson(), pr.specAsJson(), pr.updated, pr.updatedBy, pr.lifecycle); returnedVal.Err() == nil { klog.Infof("pkgRevUpdateDB:: query succeeded, row created") - return nil } else { klog.Infof("pkgRevUpdateDB:: query failed %q", returnedVal.Err()) return returnedVal.Err() } + + if err := pkgRevResourcesWriteToDB(pr); err == nil { + klog.Infof("pkgRevWriteToDB: resources written to DB") + return nil + } else { + klog.Infof("pkgRevWriteToDB: resources write to DB failed: %q", err) + return err + } } func pkgRevDeleteFromDB(prk repository.PackageRevisionKey) error { klog.Infof("pkgRevDeleteFromDB: deleting package revision %q", prk) - sqlStatement := `DELETE FROM package_revisions WHERE namespace=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4` + if err := pkgRevResourcesDeleteFromDB(prk); err == nil { + klog.Infof("pkgRevDeleteFromDB: resources deleted from DB") + } else { + klog.Infof("pkgRevWriteToDB: resources delete from DB failed: %q", err) + return err + } + + sqlStatement := `DELETE FROM package_revisions WHERE name_space=$1 AND repo_name=$2 AND package_name=$3 AND package_rev=$4 AND workspace_name=$5` returnedVal := GetDBConnection().db.QueryRow(sqlStatement, - prk.Namespace, prk.Repository, prk.Package, prk.Revision) + prk.Namespace, prk.Repository, prk.Package, prk.Revision, prk.WorkspaceName) if returnedVal.Err() == nil { klog.Infof("pkgRevDeleteFromDB: deleted package revision %q", prk) diff --git a/pkg/cache/dbcache/dbpackagesql.go b/pkg/cache/dbcache/dbpackagesql.go index c0cb3a81..0a3c0258 100644 --- a/pkg/cache/dbcache/dbpackagesql.go +++ b/pkg/cache/dbcache/dbpackagesql.go @@ -15,30 +15,45 @@ package dbcache import ( + "database/sql" + "github.com/nephio-project/porch/pkg/repository" "k8s.io/klog/v2" ) func pkgReadFromDB(pk repository.PackageKey) (dbPackage, error) { - sqlStatement := `SELECT * FROM packages WHERE namespace=$1 AND repo_name=$2 AND package_name=$3` + sqlStatement := `SELECT * FROM packages WHERE name_space=$1 AND repo_name=$2 AND package_name=$3` var dbPkg dbPackage + var metaAsJson, specAsJson string klog.Infof("pkgReadFromDB: running query [%q] on %q", sqlStatement, pk) err := GetDBConnection().db.QueryRow(sqlStatement, pk.Namespace, pk.Repository, pk.Package).Scan( &dbPkg.pkgKey.Namespace, &dbPkg.pkgKey.Repository, &dbPkg.pkgKey.Package, + &metaAsJson, + &specAsJson, &dbPkg.updated, &dbPkg.updatedBy) - klog.Infof("pkgReadFromDB: query result on %q: err=%q", pk, err) + if err != nil { + if err == sql.ErrNoRows { + klog.Infof("pkgReadFromDB: package not found in db %q", pk) + } else { + klog.Infof("pkgReadFromDB: reading package %q returned err: %q", pk, err) + } + return dbPkg, err + } + + dbPkg.setMetaFromJson(metaAsJson) + dbPkg.setSpecFromJson(specAsJson) return dbPkg, err } func pkgReadPkgsFromDB(rk repository.RepositoryKey) ([]dbPackage, error) { - sqlStatement := `SELECT * FROM packages WHERE namespace=$1 AND repo_name=$2` + sqlStatement := `SELECT * FROM packages WHERE name_space=$1 AND repo_name=$2` var dbPkgs []dbPackage @@ -52,14 +67,20 @@ func pkgReadPkgsFromDB(rk repository.RepositoryKey) ([]dbPackage, error) { for rows.Next() { var pkg dbPackage + var metaAsJson, specAsJson string rows.Scan( &pkg.pkgKey.Namespace, &pkg.pkgKey.Repository, &pkg.pkgKey.Package, + &metaAsJson, + &specAsJson, &pkg.updated, &pkg.updatedBy) + pkg.setMetaFromJson(metaAsJson) + pkg.setSpecFromJson(specAsJson) + dbPkgs = append(dbPkgs, pkg) } @@ -68,14 +89,14 @@ func pkgReadPkgsFromDB(rk repository.RepositoryKey) ([]dbPackage, error) { func pkgWriteToDB(p *dbPackage) error { sqlStatement := ` - INSERT INTO packages (namespace, repo_name, package_name, updated, updatedby) - VALUES ($1, $2, $3, $4, $5)` + INSERT INTO packages (name_space, repo_name, package_name, meta, spec, updated, updatedby) + VALUES ($1, $2, $3, $4, $5, $6, $7)` klog.Infof("pkgWriteToDB: running query [%q] on %q", sqlStatement, p.Key()) pk := p.Key() if returnedVal := GetDBConnection().db.QueryRow( - sqlStatement, pk.Namespace, pk.Repository, pk.Package, p.updated, p.updatedBy); returnedVal.Err() == nil { + sqlStatement, pk.Namespace, pk.Repository, pk.Package, p.metaAsJson(), p.specAsJson(), p.updated, p.updatedBy); returnedVal.Err() == nil { klog.Infof("pkgWriteToDB: query succeeded for %q", p.Key()) return nil } else { @@ -86,15 +107,15 @@ func pkgWriteToDB(p *dbPackage) error { func pkgUpdateDB(p *dbPackage) error { sqlStatement := ` - UPDATE packages SET updated=$4, updatedby=$5 - WHERE namespace=$1 AND repo_name=$2 AND package_name=$3` + UPDATE packages SET meta=$4, spec=$5, updated=$6, updatedby=$7 + WHERE name_space=$1 AND repo_name=$2 AND package_name=$3` klog.Infof("pkgUpdateDB: running query [%q] on %q)", sqlStatement, p.Key()) pk := p.Key() if returnedVal := GetDBConnection().db.QueryRow( sqlStatement, - pk.Namespace, pk.Repository, pk.Package, p.updated, p.updatedBy); returnedVal.Err() == nil { + pk.Namespace, pk.Repository, pk.Package, p.metaAsJson(), p.specAsJson(), p.updated, p.updatedBy); returnedVal.Err() == nil { klog.Infof("pkgUpdateDB: query succeeded for %q", pk) return nil } else { @@ -104,7 +125,7 @@ func pkgUpdateDB(p *dbPackage) error { } func pkgDeleteFromDB(pk repository.PackageKey) error { - sqlStatement := `DELETE FROM packages WHERE namespace=$1 AND repo_name=$2 AND package_name=$3` + sqlStatement := `DELETE FROM packages WHERE name_space=$1 AND repo_name=$2 AND package_name=$3` klog.Infof("DB Connection: running query [%q] on %q", sqlStatement, pk) if returnedVal := GetDBConnection().db.QueryRow(sqlStatement, pk.Namespace, pk.Repository, pk.Package); returnedVal.Err() == nil { diff --git a/pkg/cache/dbcache/dbrepository.go b/pkg/cache/dbcache/dbrepository.go index e8c7f961..177a63b6 100644 --- a/pkg/cache/dbcache/dbrepository.go +++ b/pkg/cache/dbcache/dbrepository.go @@ -111,9 +111,9 @@ func (r *dbRepository) CreatePackageRevision(ctx context.Context, newPR *v1alpha _, span := tracer.Start(ctx, "dbRepository::CreatePackageRevision", trace.WithAttributes()) defer span.End() - return &dbPackageRevision{ + dbPkgRev := &dbPackageRevision{ pkgRevKey: repository.PackageRevisionKey{ - Namespace: r.repoKey.Repository, + Namespace: r.repoKey.Namespace, Repository: r.repoKey.Repository, Package: newPR.Spec.PackageName, Revision: "", @@ -125,7 +125,11 @@ func (r *dbRepository) CreatePackageRevision(ctx context.Context, newPR *v1alpha updated: time.Now(), updatedBy: getCurrentUser(), tasks: newPR.Spec.Tasks, - }, nil + } + + prDraft, err := r.savePackageRevision(ctx, dbPkgRev, "") + + return repository.PackageRevisionDraft(prDraft), err } func (r *dbRepository) DeletePackageRevision(ctx context.Context, old repository.PackageRevision) error { @@ -249,7 +253,16 @@ func (r *dbRepository) Close() error { } func (r *dbRepository) ClosePackageRevisionDraft(ctx context.Context, prd repository.PackageRevisionDraft, version string) (repository.PackageRevision, error) { - ctx, span := tracer.Start(ctx, "dbRepository::ClosePackageRevisionDraft", trace.WithAttributes()) + _, span := tracer.Start(ctx, "dbRepository::ClosePackageRevisionDraft", trace.WithAttributes()) + defer span.End() + + pr, err := r.savePackageRevision(ctx, prd, version) + + return repository.PackageRevision(pr), err +} + +func (r *dbRepository) savePackageRevision(ctx context.Context, prd repository.PackageRevisionDraft, _ string) (*dbPackageRevision, error) { + _, span := tracer.Start(ctx, "dbRepository::savePackageRevision", trace.WithAttributes()) defer span.End() d := prd.(*dbPackageRevision) @@ -266,12 +279,12 @@ func (r *dbRepository) ClosePackageRevisionDraft(ctx context.Context, prd reposi updatedBy: d.updatedBy, } - if _, err := dbPkg.createPackage(); err != nil { + if _, err := dbPkg.savePackage(); err != nil { return nil, err } } - pkgRev, err := dbPkg.createPackageRevision(d) + pkgRev, err := dbPkg.savePackageRevision(d) if err != nil { return nil, err } diff --git a/pkg/cache/dbcache/dbrepositorysql.go b/pkg/cache/dbcache/dbrepositorysql.go index 75d0815c..ee0adeeb 100644 --- a/pkg/cache/dbcache/dbrepositorysql.go +++ b/pkg/cache/dbcache/dbrepositorysql.go @@ -20,7 +20,7 @@ import ( ) func repoReadFromDB(rk repository.RepositoryKey) (*dbRepository, error) { - sqlStatement := `SELECT namespace, repo_name, meta, spec, updated, updatedby, deployment FROM repositories WHERE namespace=$1 AND repo_name=$2` + sqlStatement := `SELECT name_space, repo_name, meta, spec, updated, updatedby, deployment FROM repositories WHERE name_space=$1 AND repo_name=$2` var dbRepo dbRepository var metaAsJson, specAsJson string @@ -42,7 +42,7 @@ func repoReadFromDB(rk repository.RepositoryKey) (*dbRepository, error) { func repoWriteToDB(r *dbRepository) error { sqlStatement := ` - INSERT INTO repositories (namespace, repo_name, meta, spec, updated, updatedby, deployment) + INSERT INTO repositories (name_space, repo_name, meta, spec, updated, updatedby, deployment) VALUES ($1, $2, $3, $4, $5, $6, $7)` klog.Infof("DB Connection: running query [%q] on repository (%#v)", sqlStatement, r) @@ -62,7 +62,7 @@ func repoWriteToDB(r *dbRepository) error { func repoUpdateDB(r *dbRepository) error { sqlStatement := ` UPDATE repositories SET meta=$3, spec=$4, updated=$5, updatedby=$6, deployment=$7 - WHERE namespace=$1 AND repo_name=$2` + WHERE name_space=$1 AND repo_name=$2` klog.Infof("repoUpdateDB: running query [%q] on %q)", sqlStatement, r.Key()) @@ -79,7 +79,7 @@ func repoUpdateDB(r *dbRepository) error { } func repoDeleteFromDB(rk repository.RepositoryKey) error { - sqlStatement := `DELETE FROM repositories WHERE namespace=$1 AND repo_name=$2` + sqlStatement := `DELETE FROM repositories WHERE name_space=$1 AND repo_name=$2` returnedVal := GetDBConnection().db.QueryRow(sqlStatement, rk.Namespace, rk.Repository) diff --git a/pkg/util/util.go b/pkg/util/util.go index c331b586..2a7cef74 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -103,9 +103,16 @@ func SchemaToMetaGVR(gvr schema.GroupVersionResource) metav1.GroupVersionResourc } func ParseRepositoryName(name string) (string, error) { - lastDash := strings.LastIndex(name, "-") - if lastDash < 0 { - return "", fmt.Errorf("malformed package revision name; expected at least one hyphen: %q", name) + if strings.Contains(name, ".") { + // Distringuished handling of package names + firstDot := strings.Index(name, ".") + return name[:firstDot], nil + } else { + // Default handling of package names + lastDash := strings.LastIndex(name, "-") + if lastDash < 0 { + return "", fmt.Errorf("malformed package revision name; expected at least one hyphen: %q", name) + } + return name[:lastDash], nil } - return name[:lastDash], nil }