Skip to content

Commit d60c1f3

Browse files
authored
Merge pull request kptdev#309 from Nordix/creation-timestamp-upstream-lock
DB Cache locks and creationTimestamp enhancements
2 parents 20bd156 + 687f6d1 commit d60c1f3

19 files changed

Lines changed: 374 additions & 166 deletions

api/sql/porch-db-1.5.2-1.5.3.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
Copyright 2025 The kpt and Nephio Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
ALTER TABLE package_revisions
17+
ADD COLUMN ext_pr_id TEXT NOT NULL
18+
DEFAULT '{}';

api/sql/porch-db-1.5.3-1.5.2.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
Copyright 2025 The kpt and Nephio Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
ALTER TABLE package_revisions
17+
DROP COLUMN ext_pr_id;

api/sql/porch-db.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ CREATE TABLE IF NOT EXISTS package_revisions (
8282
updated TIMESTAMP NOT NULL,
8383
updatedby TEXT NOT NULL,
8484
lifecycle TEXT CHECK (lifecycle IN ('Draft', 'Proposed', 'Published', 'DeletionProposed')) NOT NULL,
85+
ext_pr_id TEXT NOT NULL,
8586
latest BOOLEAN NOT NULL DEFAULT FALSE,
8687
tasks TEXT NOT NULL,
8788
PRIMARY KEY (k8s_name_space, k8s_name),

pkg/cache/dbcache/dbcache_test.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
cachetypes "github.com/nephio-project/porch/pkg/cache/types"
2727
"github.com/nephio-project/porch/pkg/externalrepo"
2828
"github.com/nephio-project/porch/pkg/repository"
29-
mocksql "github.com/nephio-project/porch/test/mockery/mocks/porch/pkg/cache/dbcache"
29+
mockdbcache "github.com/nephio-project/porch/test/mockery/mocks/porch/pkg/cache/dbcache"
3030
"github.com/stretchr/testify/assert"
3131
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3232
"k8s.io/apimachinery/pkg/watch"
@@ -126,7 +126,7 @@ func (n *mockNotifier) NotifyPackageRevisionChange(eventType watch.EventType, ob
126126
}
127127

128128
func switchToMockSQL(t *testing.T) {
129-
mockSQL := mocksql.NewMockdbSQLInterface(t)
129+
mockDBCache := mockdbcache.NewMockdbSQLInterface(t)
130130

131131
savedDBHandler = GetDB()
132132
dbHandler = nil
@@ -137,7 +137,7 @@ func switchToMockSQL(t *testing.T) {
137137
dbHandler = &DBHandler{
138138
dBCacheOptions: savedDBHandler.dBCacheOptions,
139139
dataSource: savedDBHandler.dataSource,
140-
db: mockSQL,
140+
db: mockDBCache,
141141
}
142142
assert.NotNil(t, dbHandler)
143143
}
@@ -180,18 +180,25 @@ func TestDBRepositoryCrud(t *testing.T) {
180180
assert.Nil(t, err)
181181
}
182182

183-
func createTestRepo(t *testing.T, namespace, name string) dbRepository {
183+
func createTestRepo(t *testing.T, namespace, name string) *dbRepository {
184184
dbRepo := dbRepository{
185185
repoKey: repository.RepositoryKey{
186186
Namespace: namespace,
187187
Name: name,
188188
},
189189
repoPRChangeNotifier: &mockNotifier{returnVal: 1},
190+
spec: &configapi.Repository{
191+
Spec: configapi.RepositorySpec{
192+
Git: &configapi.GitRepository{
193+
Repo: "http://www.gitrepo.org/my-repo",
194+
},
195+
},
196+
},
190197
}
191198
err := repoWriteToDB(context.TODO(), &dbRepo)
192199
assert.Nil(t, err)
193200

194-
return dbRepo
201+
return &dbRepo
195202
}
196203

197204
func deleteTestRepo(t *testing.T, key repository.RepositoryKey) {

pkg/cache/dbcache/dbpackage.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ func (p *dbPackage) GetPackage(ctx context.Context) *v1alpha1.PorchPackage {
109109
}
110110
}
111111

112-
func (p *dbPackage) savePackageRevision(ctx context.Context, d *dbPackageRevision) (*dbPackageRevision, error) {
112+
func (p *dbPackage) savePackageRevision(ctx context.Context, d *dbPackageRevision, saveResources bool) (*dbPackageRevision, error) {
113113
_, span := tracer.Start(ctx, "dbPackage:savePackageRevision", trace.WithAttributes())
114114
defer span.End()
115115

116-
return d.savePackageRevision(ctx, true)
116+
return d.savePackageRevision(ctx, saveResources)
117117
}
118118

119119
func (p *dbPackage) DeletePackageRevision(ctx context.Context, old repository.PackageRevision, deleteExternal bool) error {

pkg/cache/dbcache/dbpackagerevision.go

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type dbPackageRevision struct {
5050
updated time.Time
5151
updatedBy string
5252
lifecycle porchapi.PackageRevisionLifecycle
53+
extPRID kptfile.UpstreamLock
5354
latest bool
5455
tasks []porchapi.Task
5556
resources map[string]string
@@ -83,7 +84,7 @@ func (pr *dbPackageRevision) savePackageRevision(ctx context.Context, saveResour
8384
_, err := pkgRevReadFromDB(ctx, pr.Key(), false)
8485
if err == nil {
8586
updErr := pkgRevUpdateDB(ctx, pr, saveResources)
86-
if updErr == nil {
87+
if updErr == nil && saveResources {
8788
sent := pr.repo.repoPRChangeNotifier.NotifyPackageRevisionChange(watch.Modified, pr)
8889
klog.Infof("DB cache %+v: sent %d notifications for updated package revision %+v", pr.repo.Key(), sent, pr.Key())
8990
}
@@ -151,29 +152,11 @@ func (pr *dbPackageRevision) GetPackageRevision(ctx context.Context) (*porchapi.
151152
}
152153
}
153154

154-
_, lock, _ := pr.GetUpstreamLock(ctx)
155-
lockCopy := &porchapi.UpstreamLock{}
156-
157-
// TODO: Comment copied from pkg/externalrepo/git/package.go
158-
// Use kpt definition of UpstreamLock in the package revision status
159-
// when https://github.com/GoogleContainerTools/kpt/issues/3297 is complete.
160-
// Until then, we have to translate from one type to another.
161-
if lock.Git != nil {
162-
lockCopy = &porchapi.UpstreamLock{
163-
Type: porchapi.OriginType(lock.Type),
164-
Git: &porchapi.GitLock{
165-
Repo: lock.Git.Repo,
166-
Directory: lock.Git.Directory,
167-
Commit: lock.Git.Commit,
168-
Ref: lock.Git.Ref,
169-
},
170-
}
171-
}
172-
155+
_, upstreamLock, _ := pr.GetUpstreamLock(ctx)
173156
kf, _ := readPR.GetKptfile(ctx)
174157

175158
status := porchapi.PackageRevisionStatus{
176-
UpstreamLock: lockCopy,
159+
UpstreamLock: repository.KptUpstreamLock2APIUpstreamLock(upstreamLock),
177160
Deployment: pr.repo.deployment,
178161
Conditions: repository.ToAPIConditions(kf),
179162
}
@@ -293,11 +276,14 @@ func (pr *dbPackageRevision) ToMainPackageRevision(ctx context.Context) reposito
293276
updated: time.Now(),
294277
updatedBy: getCurrentUser(),
295278
lifecycle: pr.lifecycle,
279+
extPRID: pr.extPRID,
296280
latest: false,
297281
tasks: pr.tasks,
298282
resources: pr.resources,
299283
}
300284

285+
mainPR.meta.CreationTimestamp = metav1.Time{Time: time.Now()}
286+
301287
if mainPR.pkgRevKey.WorkspaceName == "" {
302288
mainPR.pkgRevKey.WorkspaceName = "main"
303289
}
@@ -336,31 +322,7 @@ func (pr *dbPackageRevision) GetKptfile(ctx context.Context) (kptfile.KptFile, e
336322
}
337323

338324
func (pr *dbPackageRevision) GetLock() (kptfile.Upstream, kptfile.UpstreamLock, error) {
339-
if porchapi.LifecycleIsPublished(pr.lifecycle) {
340-
externalPr, err := pr.repo.getExternalPr(context.Background(), pr.Key())
341-
if err != nil {
342-
return kptfile.Upstream{}, kptfile.UpstreamLock{},
343-
pkgerrors.Wrapf(err, "dbPackageRevision:GetLock: getting lock of %+v failed, could not find package revision on external repository", pr.Key())
344-
}
345-
346-
return externalPr.GetLock()
347-
} else {
348-
return kptfile.Upstream{
349-
Type: kptfile.GitOrigin,
350-
Git: &kptfile.Git{
351-
Repo: pr.repo.spec.Spec.Git.Repo,
352-
Directory: pr.Key().PKey().ToPkgPathname(),
353-
Ref: "drafts/" + pr.Key().PKey().ToPkgPathname() + "/" + pr.Key().WorkspaceName,
354-
},
355-
}, kptfile.UpstreamLock{
356-
Type: kptfile.GitOrigin,
357-
Git: &kptfile.GitLock{
358-
Repo: pr.repo.spec.Spec.Git.Repo,
359-
Directory: pr.Key().PKey().ToPkgPathname(),
360-
Ref: "drafts/" + pr.Key().PKey().ToPkgPathname() + "/" + pr.Key().WorkspaceName,
361-
},
362-
}, nil
363-
}
325+
return repository.KptUpstreamLock2KptUpstream(pr.extPRID), pr.extPRID, nil
364326
}
365327

366328
func (pr *dbPackageRevision) ResourceVersion() string {
@@ -427,25 +389,50 @@ func (pr *dbPackageRevision) publishPR(ctx context.Context, newLifecycle porchap
427389
pr.pkgRevKey.Revision = latestRev + 1
428390
pr.lifecycle = newLifecycle
429391

430-
if _, err := engine.PushPackageRevision(ctx, pr.repo.externalRepo, pr); err != nil {
392+
pushedPRExtID, err := engine.PushPackageRevision(ctx, pr.repo.externalRepo, pr)
393+
if err != nil {
431394
klog.Warningf("push of package revision %+v to external repo failed, %q", pr.Key(), err)
432395
pr.pkgRevKey.Revision = 0
433396
pr.lifecycle = porchapi.PackageRevisionLifecycleProposed
434397
return pkgerrors.Wrapf(err, "dbPackageRevision:publishPR: push of package revision %+v to external repo failed", pr.Key())
435398
}
436399

437-
if pr.pkgRevKey.Revision == 1 {
438-
if err = pkgRevWriteToDB(ctx, pr.ToMainPackageRevision(ctx).(*dbPackageRevision)); err != nil {
439-
return pkgerrors.Wrapf(err, "dbPackageRevision:UpdateLifecycle: could not write placeholder package revision for package revision %+v to DB", pr.Key())
400+
pr.extPRID = pushedPRExtID
401+
402+
if err = pkgRevUpdateDB(ctx, pr, false); err != nil {
403+
return pkgerrors.Wrapf(err, "dbPackageRevision:publishPR: failed to save package revision %+v to database after push to external repo", pr.Key())
404+
}
405+
406+
return pr.publishPlaceholderPRForPR(ctx)
407+
}
408+
409+
func (pr *dbPackageRevision) publishPlaceholderPRForPR(ctx context.Context) error {
410+
_, span := tracer.Start(ctx, "dbPackageRevision::publishPlaceholderPRForPR", trace.WithAttributes())
411+
defer span.End()
412+
413+
prWithResources := pr
414+
if len(prWithResources.resources) == 0 {
415+
if readPR, err := pkgRevReadFromDB(ctx, pr.Key(), true); err == nil {
416+
prWithResources = readPR
417+
} else {
418+
return pkgerrors.Wrapf(err, "dbPackageRevision:publishPlaceholderPRForPR: could read resources for package revision %+v to DB", pr.Key())
419+
}
420+
}
421+
422+
placeholderPR := prWithResources.ToMainPackageRevision(ctx).(*dbPackageRevision)
423+
424+
if prWithResources.pkgRevKey.Revision == 1 {
425+
if err := pkgRevWriteToDB(ctx, placeholderPR); err != nil {
426+
return pkgerrors.Wrapf(err, "dbPackageRevision:publishPlaceholderPRForPR: could not write placeholder package revision for package revision %+v to DB", placeholderPR.Key())
440427
}
441-
sent := pr.repo.repoPRChangeNotifier.NotifyPackageRevisionChange(watch.Added, pr)
442-
klog.Infof("DB cache %+v: sent %d notifications for added package revision %+v", pr.repo.Key(), sent, pr.Key())
443-
} else if pr.pkgRevKey.Revision > 1 {
444-
if err = pkgRevUpdateDB(ctx, pr.ToMainPackageRevision(ctx).(*dbPackageRevision), true); err != nil {
445-
return pkgerrors.Wrapf(err, "dbPackageRevision:UpdateLifecycle: could not update placeholder package revision for package revision %+v to DB", pr.Key())
428+
sent := placeholderPR.repo.repoPRChangeNotifier.NotifyPackageRevisionChange(watch.Added, placeholderPR)
429+
klog.Infof("DB cache %+v: sent %d notifications for added package revision %+v", placeholderPR.repo.Key(), sent, placeholderPR.Key())
430+
} else if prWithResources.pkgRevKey.Revision > 1 {
431+
if err := pkgRevUpdateDB(ctx, placeholderPR, true); err != nil {
432+
return pkgerrors.Wrapf(err, "dbPackageRevision:publishPlaceholderPRForPR: could not update placeholder package revision for package revision %+v to DB", placeholderPR.Key())
446433
}
447-
sent := pr.repo.repoPRChangeNotifier.NotifyPackageRevisionChange(watch.Modified, pr)
448-
klog.Infof("DB cache %+v: sent %d notifications for updated package revision %+v", pr.repo.Key(), sent, pr.Key())
434+
sent := placeholderPR.repo.repoPRChangeNotifier.NotifyPackageRevisionChange(watch.Modified, placeholderPR)
435+
klog.Infof("DB cache %+v: sent %d notifications for updated package revision %+v", placeholderPR.repo.Key(), sent, placeholderPR.Key())
449436
}
450437

451438
return nil

pkg/cache/dbcache/dbpackagerevision_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func TestDBPackageRevision(t *testing.T) {
4747
},
4848
},
4949
}
50-
mockCache.EXPECT().GetRepository(mock.Anything).Return(&testRepo).Maybe()
50+
mockCache.EXPECT().GetRepository(mock.Anything).Return(testRepo).Maybe()
5151

5252
err := testRepo.OpenRepository(ctx, externalrepotypes.ExternalRepoOptions{})
5353
assert.Nil(t, err)

0 commit comments

Comments
 (0)