From b45bdca90577fb4bc65ef588f217dbb6db8c2b53 Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Wed, 21 Aug 2024 11:09:58 +0200 Subject: [PATCH] Skip release archive Don't archive the release any more and move the announcement to the release artifacts (`kubernetes-release/release/v1.x.y`). Signed-off-by: Sascha Grunert --- cmd/krel/cmd/announce_build.go | 4 +- cmd/krel/cmd/announce_send.go | 2 +- cmd/krel/cmd/sign_blobs.go | 2 +- pkg/anago/anago.go | 24 +- pkg/anago/anago_test.go | 9 +- pkg/anago/anagofakes/fake_release_client.go | 65 --- pkg/anago/anagofakes/fake_release_impl.go | 74 --- pkg/anago/release.go | 70 +-- pkg/announce/announce.go | 7 +- pkg/announce/impl.go | 4 +- pkg/release/archive.go | 368 ------------- pkg/release/archive_test.go | 82 --- pkg/release/archive_unit_test.go | 168 ------ pkg/release/doc.go | 1 - pkg/release/release.go | 3 - .../releasefakes/fake_archiver_impl.go | 508 ------------------ 16 files changed, 51 insertions(+), 1340 deletions(-) delete mode 100644 pkg/release/archive.go delete mode 100644 pkg/release/archive_test.go delete mode 100644 pkg/release/archive_unit_test.go delete mode 100644 pkg/release/releasefakes/fake_archiver_impl.go diff --git a/cmd/krel/cmd/announce_build.go b/cmd/krel/cmd/announce_build.go index d73229b2f48..2c3f44df220 100644 --- a/cmd/krel/cmd/announce_build.go +++ b/cmd/krel/cmd/announce_build.go @@ -29,6 +29,8 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/release-utils/command" + + "k8s.io/release/pkg/announce" ) const ( @@ -240,7 +242,7 @@ func (opts *buildAnnounceOptions) saveAnnouncement(announcementSubject string, a return fmt.Errorf("saving announcement.html: %w", err) } - absOutputPath = filepath.Join(opts.workDir, "announcement-subject.txt") + absOutputPath = filepath.Join(opts.workDir, announce.SubjectFile) logrus.Infof("Writing announcement subject to %s", absOutputPath) err = os.WriteFile(absOutputPath, []byte(announcementSubject), os.FileMode(0o644)) if err != nil { diff --git a/cmd/krel/cmd/announce_send.go b/cmd/krel/cmd/announce_send.go index 2469867d1ae..301594ee457 100644 --- a/cmd/krel/cmd/announce_send.go +++ b/cmd/krel/cmd/announce_send.go @@ -117,7 +117,7 @@ func runAnnounce(opts *sendAnnounceOptions, announceRootOpts *announceOptions, r tag := util.AddTagPrefix(announceRootOpts.tag) u := fmt.Sprintf( - "%s/archive/anago-%s/announcement.html", + "%s/release/%s/announcement.html", release.URLPrefixForBucket(release.ProductionBucket), tag, ) logrus.Infof("Using announcement remote URL: %s", u) diff --git a/cmd/krel/cmd/sign_blobs.go b/cmd/krel/cmd/sign_blobs.go index 00e4fe6892c..b0b7ade029c 100644 --- a/cmd/krel/cmd/sign_blobs.go +++ b/cmd/krel/cmd/sign_blobs.go @@ -196,7 +196,7 @@ func runSignBlobs(signOpts *signOptions, signBlobOpts *signBlobOptions, args []s } } - t := throttler.New(int(signOpts.maxWorkers), len(bundle)) //nolint:gosec // overlow is highly unlikely + t := throttler.New(int(signOpts.maxWorkers), len(bundle)) //nolint:gosec // overflow is highly unlikely for _, fileBundle := range bundle { go func(fileBundle signingBundle) { logrus.Infof("Signing %s...", fileBundle.fileToSign) diff --git a/pkg/anago/anago.go b/pkg/anago/anago.go index ffaa72cdda7..ec1ef05ebbc 100644 --- a/pkg/anago/anago.go +++ b/pkg/anago/anago.go @@ -29,6 +29,7 @@ import ( "sigs.k8s.io/release-utils/util" "sigs.k8s.io/release-utils/version" + "k8s.io/release/pkg/announce" "k8s.io/release/pkg/release" ) @@ -51,6 +52,12 @@ const ( // releaseNotesJSONFile is the file containing the release notes in json format. releaseNotesJSONFile = workspaceDir + "/src/release-notes.json" + // announcementHTMLFile is the file containing the release announcement in HTML format. + announcementHTMLFile = workspaceDir + "/src/" + announce.AnnouncementFile + + // announcementSubjectFile is the file containing the release announcement subject. + announcementSubjectFile = workspaceDir + "/src/" + announce.SubjectFile + // The default license for all artifacts. LicenseIdentifier = "Apache-2.0" ) @@ -395,7 +402,7 @@ func (r *Release) Run() error { return fmt.Errorf("init log file: %w", err) } - logger := log.NewStepLogger(12) + logger := log.NewStepLogger(11) v := version.GetVersionInfo() logger.Infof("Using krel version: %s", v.GitVersion) @@ -431,6 +438,11 @@ func (r *Release) Run() error { logrus.Warnf("Unable to check provenance attestation: %v", err) } + logger.WithStep().Info("Creating announcement") + if err := r.client.CreateAnnouncement(); err != nil { + return fmt.Errorf("create announcement: %w", err) + } + logger.WithStep().Info("Pushing artifacts") if err := r.client.PushArtifacts(); err != nil { return fmt.Errorf("push artifacts: %w", err) @@ -441,21 +453,11 @@ func (r *Release) Run() error { return fmt.Errorf("push git objects: %w", err) } - logger.WithStep().Info("Creating announcement") - if err := r.client.CreateAnnouncement(); err != nil { - return fmt.Errorf("create announcement: %w", err) - } - logger.WithStep().Info("Updating GitHub release page") if err := r.client.UpdateGitHubPage(); err != nil { return fmt.Errorf("updating github page: %w", err) } - logger.WithStep().Info("Archiving release") - if err := r.client.Archive(); err != nil { - return fmt.Errorf("archive release: %w", err) - } - logger.Info("Release done") return nil } diff --git a/pkg/anago/anago_test.go b/pkg/anago/anago_test.go index e3133a11eea..a4ce4437670 100644 --- a/pkg/anago/anago_test.go +++ b/pkg/anago/anago_test.go @@ -46,6 +46,7 @@ func mockGenerateReleaseVersionRelease(mock *anagofakes.FakeReleaseClient) { mock.GenerateReleaseVersionReturns(nil) } +//nolint:dupl // duplications in those tests are intentional func TestRunStage(t *testing.T) { for _, tc := range []struct { prepare func(*anagofakes.FakeStageClient) @@ -131,6 +132,7 @@ func TestRunStage(t *testing.T) { } } +//nolint:dupl // duplications in those tests are intentional func TestRunRelease(t *testing.T) { for _, tc := range []struct { prepare func(*anagofakes.FakeReleaseClient) @@ -200,13 +202,6 @@ func TestRunRelease(t *testing.T) { }, shouldError: true, }, - { // Archive fails - prepare: func(mock *anagofakes.FakeReleaseClient) { - mockGenerateReleaseVersionRelease(mock) - mock.ArchiveReturns(err) - }, - shouldError: true, - }, } { opts := anago.DefaultReleaseOptions() sut := anago.NewRelease(opts) diff --git a/pkg/anago/anagofakes/fake_release_client.go b/pkg/anago/anagofakes/fake_release_client.go index baa82db44b2..78caee1107e 100644 --- a/pkg/anago/anagofakes/fake_release_client.go +++ b/pkg/anago/anagofakes/fake_release_client.go @@ -22,16 +22,6 @@ import ( ) type FakeReleaseClient struct { - ArchiveStub func() error - archiveMutex sync.RWMutex - archiveArgsForCall []struct { - } - archiveReturns struct { - result1 error - } - archiveReturnsOnCall map[int]struct { - result1 error - } CheckPrerequisitesStub func() error checkPrerequisitesMutex sync.RWMutex checkPrerequisitesArgsForCall []struct { @@ -161,59 +151,6 @@ type FakeReleaseClient struct { invocationsMutex sync.RWMutex } -func (fake *FakeReleaseClient) Archive() error { - fake.archiveMutex.Lock() - ret, specificReturn := fake.archiveReturnsOnCall[len(fake.archiveArgsForCall)] - fake.archiveArgsForCall = append(fake.archiveArgsForCall, struct { - }{}) - stub := fake.ArchiveStub - fakeReturns := fake.archiveReturns - fake.recordInvocation("Archive", []interface{}{}) - fake.archiveMutex.Unlock() - if stub != nil { - return stub() - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeReleaseClient) ArchiveCallCount() int { - fake.archiveMutex.RLock() - defer fake.archiveMutex.RUnlock() - return len(fake.archiveArgsForCall) -} - -func (fake *FakeReleaseClient) ArchiveCalls(stub func() error) { - fake.archiveMutex.Lock() - defer fake.archiveMutex.Unlock() - fake.ArchiveStub = stub -} - -func (fake *FakeReleaseClient) ArchiveReturns(result1 error) { - fake.archiveMutex.Lock() - defer fake.archiveMutex.Unlock() - fake.ArchiveStub = nil - fake.archiveReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeReleaseClient) ArchiveReturnsOnCall(i int, result1 error) { - fake.archiveMutex.Lock() - defer fake.archiveMutex.Unlock() - fake.ArchiveStub = nil - if fake.archiveReturnsOnCall == nil { - fake.archiveReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.archiveReturnsOnCall[i] = struct { - result1 error - }{result1} -} - func (fake *FakeReleaseClient) CheckPrerequisites() error { fake.checkPrerequisitesMutex.Lock() ret, specificReturn := fake.checkPrerequisitesReturnsOnCall[len(fake.checkPrerequisitesArgsForCall)] @@ -885,8 +822,6 @@ func (fake *FakeReleaseClient) ValidateOptionsReturnsOnCall(i int, result1 error func (fake *FakeReleaseClient) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.archiveMutex.RLock() - defer fake.archiveMutex.RUnlock() fake.checkPrerequisitesMutex.RLock() defer fake.checkPrerequisitesMutex.RUnlock() fake.checkProvenanceMutex.RLock() diff --git a/pkg/anago/anagofakes/fake_release_impl.go b/pkg/anago/anagofakes/fake_release_impl.go index 4d8a5ec4ace..74f47c72bfa 100644 --- a/pkg/anago/anagofakes/fake_release_impl.go +++ b/pkg/anago/anagofakes/fake_release_impl.go @@ -30,17 +30,6 @@ import ( ) type FakeReleaseImpl struct { - ArchiveReleaseStub func(*release.ArchiverOptions) error - archiveReleaseMutex sync.RWMutex - archiveReleaseArgsForCall []struct { - arg1 *release.ArchiverOptions - } - archiveReleaseReturns struct { - result1 error - } - archiveReleaseReturnsOnCall map[int]struct { - result1 error - } BranchNeedsCreationStub func(string, string, semver.Version) (bool, error) branchNeedsCreationMutex sync.RWMutex branchNeedsCreationArgsForCall []struct { @@ -309,67 +298,6 @@ type FakeReleaseImpl struct { invocationsMutex sync.RWMutex } -func (fake *FakeReleaseImpl) ArchiveRelease(arg1 *release.ArchiverOptions) error { - fake.archiveReleaseMutex.Lock() - ret, specificReturn := fake.archiveReleaseReturnsOnCall[len(fake.archiveReleaseArgsForCall)] - fake.archiveReleaseArgsForCall = append(fake.archiveReleaseArgsForCall, struct { - arg1 *release.ArchiverOptions - }{arg1}) - stub := fake.ArchiveReleaseStub - fakeReturns := fake.archiveReleaseReturns - fake.recordInvocation("ArchiveRelease", []interface{}{arg1}) - fake.archiveReleaseMutex.Unlock() - if stub != nil { - return stub(arg1) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeReleaseImpl) ArchiveReleaseCallCount() int { - fake.archiveReleaseMutex.RLock() - defer fake.archiveReleaseMutex.RUnlock() - return len(fake.archiveReleaseArgsForCall) -} - -func (fake *FakeReleaseImpl) ArchiveReleaseCalls(stub func(*release.ArchiverOptions) error) { - fake.archiveReleaseMutex.Lock() - defer fake.archiveReleaseMutex.Unlock() - fake.ArchiveReleaseStub = stub -} - -func (fake *FakeReleaseImpl) ArchiveReleaseArgsForCall(i int) *release.ArchiverOptions { - fake.archiveReleaseMutex.RLock() - defer fake.archiveReleaseMutex.RUnlock() - argsForCall := fake.archiveReleaseArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeReleaseImpl) ArchiveReleaseReturns(result1 error) { - fake.archiveReleaseMutex.Lock() - defer fake.archiveReleaseMutex.Unlock() - fake.ArchiveReleaseStub = nil - fake.archiveReleaseReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeReleaseImpl) ArchiveReleaseReturnsOnCall(i int, result1 error) { - fake.archiveReleaseMutex.Lock() - defer fake.archiveReleaseMutex.Unlock() - fake.ArchiveReleaseStub = nil - if fake.archiveReleaseReturnsOnCall == nil { - fake.archiveReleaseReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.archiveReleaseReturnsOnCall[i] = struct { - result1 error - }{result1} -} - func (fake *FakeReleaseImpl) BranchNeedsCreation(arg1 string, arg2 string, arg3 semver.Version) (bool, error) { fake.branchNeedsCreationMutex.Lock() ret, specificReturn := fake.branchNeedsCreationReturnsOnCall[len(fake.branchNeedsCreationArgsForCall)] @@ -1699,8 +1627,6 @@ func (fake *FakeReleaseImpl) ValidateImagesReturnsOnCall(i int, result1 error) { func (fake *FakeReleaseImpl) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.archiveReleaseMutex.RLock() - defer fake.archiveReleaseMutex.RUnlock() fake.branchNeedsCreationMutex.RLock() defer fake.branchNeedsCreationMutex.RUnlock() fake.checkPrerequisitesMutex.RLock() diff --git a/pkg/anago/release.go b/pkg/anago/release.go index 2b1be6ca2c8..53884a874c1 100644 --- a/pkg/anago/release.go +++ b/pkg/anago/release.go @@ -90,10 +90,6 @@ type releaseClient interface { // UpdateGitHubPage updates the GitHub release page to with the source code // and release information. UpdateGitHubPage() error - - // Archive copies the release process logs to a bucket and sets private - // permissions on it. - Archive() error } // DefaultRelease is the default staging implementation used in production. @@ -154,7 +150,6 @@ type releaseImpl interface { PushBranches(pusher *release.GitObjectPusher, branchList []string) error PushMainBranch(pusher *release.GitObjectPusher) error NewGitPusher(opts *release.GitObjectPusherOptions) (*release.GitObjectPusher, error) - ArchiveRelease(options *release.ArchiverOptions) error NormalizePath(store object.Store, pathParts ...string) (string, error) CopyToRemote(store object.Store, src, gcsPath string) error PublishReleaseNotesIndex( @@ -265,11 +260,6 @@ func (d *defaultReleaseImpl) CreateAnnouncement(options *announce.Options) error return announce.NewAnnounce(options).CreateForRelease() } -func (d *defaultReleaseImpl) ArchiveRelease(options *release.ArchiverOptions) error { - // Create a new release archiver - return release.NewArchiver(options).ArchiveRelease() -} - func (d *defaultReleaseImpl) UpdateGitHubPage(options *github.Options) error { return github.NewGitHub(options).UpdateGitHubPage() } @@ -427,7 +417,7 @@ func (d *DefaultRelease) PushArtifacts() error { } } - logrus.Info("Publishing release notes JSON") + logrus.Info("Publishing release notes JSON and announcement") objStore := object.NewGCS() objStore.SetOptions(objStore.WithNoClobber(false)) gcsReleaseRootPath, err := d.impl.NormalizePath( @@ -441,12 +431,18 @@ func (d *DefaultRelease) PushArtifacts() error { "/%s/release-notes.json", d.state.versions.Prime(), ) - if err := d.impl.CopyToRemote( - objStore, - releaseNotesJSONFile, - gcsReleaseNotesPath, - ); err != nil { - return fmt.Errorf("copy release notes to bucket: %w", err) + for from, to := range map[string]string{ + releaseNotesJSONFile: gcsReleaseNotesPath, + announcementHTMLFile: gcsReleaseRootPath + fmt.Sprintf("/%s/%s", d.state.versions.Prime(), announce.AnnouncementFile), + announcementSubjectFile: gcsReleaseRootPath + fmt.Sprintf("/%s/%s", d.state.versions.Prime(), announce.SubjectFile), + } { + if err := d.impl.CopyToRemote( + objStore, + from, + to, + ); err != nil { + return fmt.Errorf("copy file notes to bucket: %w", err) + } } for _, version := range d.state.versions.Ordered() { @@ -564,6 +560,17 @@ func (d *DefaultRelease) CreateAnnouncement() error { logrus.Info("Not creating publishing bot issue in mock release") } } + + args := "" + if d.options.NoMock { + args += " --nomock" + } + args += " --tag=" + d.state.versions.Prime() + + logrus.Infof( + "To announce this release, run:\n\n$ krel announce send%s", args, + ) + return nil } @@ -600,35 +607,6 @@ func (d *DefaultRelease) UpdateGitHubPage() error { return nil } -// Archive stores the release artifact in a bucket along with -// its logs for long term conservation. -func (d *DefaultRelease) Archive() error { - // Create a new options set for the release archiver - archiverOptions := &release.ArchiverOptions{ - ReleaseBuildDir: filepath.Join(workspaceDir, "src"), - LogFile: d.state.logFile, - BuildVersion: d.options.BuildVersion, - PrimeVersion: d.state.versions.Prime(), - Bucket: d.options.Bucket(), - } - - if err := d.impl.ArchiveRelease(archiverOptions); err != nil { - return fmt.Errorf("running the release archival process: %w", err) - } - - args := "" - if d.options.NoMock { - args += " --nomock" - } - args += " --tag=" + d.state.versions.Prime() - - logrus.Infof( - "To announce this release, run:\n\n$ krel announce send%s", args, - ) - - return nil -} - // CheckProvenance verifies the artifacts staged in the release bucket // by verifying the provenance metadata generated during the stage run. func (d *DefaultRelease) CheckProvenance() error { diff --git a/pkg/announce/announce.go b/pkg/announce/announce.go index 8a2a3111ab4..f7492e33721 100644 --- a/pkg/announce/announce.go +++ b/pkg/announce/announce.go @@ -25,8 +25,11 @@ import ( ) const ( - announcementFile = "announcement.html" - subjectFile = "announcement-subject.txt" + // AnnouncementFile is the default announcement HTML file. + AnnouncementFile = "announcement.html" + + // SubjectFile is the default subject file for the announcement. + SubjectFile = "announcement-subject.txt" ) const branchAnnouncement = `Kubernetes Community, diff --git a/pkg/announce/impl.go b/pkg/announce/impl.go index 0faa737ca40..fa8fecf899b 100644 --- a/pkg/announce/impl.go +++ b/pkg/announce/impl.go @@ -44,7 +44,7 @@ type impl interface { } func (i *defaultImpl) Create(workDir, subject, message string) error { - subjectFile := filepath.Join(workDir, subjectFile) + subjectFile := filepath.Join(workDir, SubjectFile) //nolint:gosec // TODO(gosec): G306: Expect WriteFile permissions to be // 0600 or less if err := os.WriteFile( @@ -58,7 +58,7 @@ func (i *defaultImpl) Create(workDir, subject, message string) error { } logrus.Debugf("Wrote file %s", subjectFile) - announcementFile := filepath.Join(workDir, announcementFile) + announcementFile := filepath.Join(workDir, AnnouncementFile) //nolint:gosec // TODO(gosec): G306: Expect WriteFile permissions to be // 0600 or less if err := os.WriteFile( diff --git a/pkg/release/archive.go b/pkg/release/archive.go deleted file mode 100644 index ea2bfe5e0a2..00000000000 --- a/pkg/release/archive.go +++ /dev/null @@ -1,368 +0,0 @@ -/* -Copyright 2020 The Kubernetes 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 release - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/sirupsen/logrus" - - "sigs.k8s.io/release-sdk/gcli" - "sigs.k8s.io/release-sdk/object" - "sigs.k8s.io/release-utils/command" - "sigs.k8s.io/release-utils/tar" - "sigs.k8s.io/release-utils/util" -) - -const ( - archiveDirPrefix = "anago-" // Prefix for archive directories - archiveBucketPath = "archive" // Archive sibdirectory in bucket - logsArchiveSubPath = "logs" // Logs subdirectory -) - -// Archiver stores the release build directory in a bucket -// along with it's logs. -type Archiver struct { - impl archiverImpl - opts *ArchiverOptions -} - -// NewArchiver create a new archiver with the default implementation. -func NewArchiver(opts *ArchiverOptions) *Archiver { - return &Archiver{&defaultArchiverImpl{}, opts} -} - -// SetImpl changes the archiver implementation. -func (archiver *Archiver) SetImpl(impl archiverImpl) { - archiver.impl = impl -} - -// ArchiverOptions set the options used when archiving a release. -type ArchiverOptions struct { - ReleaseBuildDir string // Build directory that will be archived - LogFile string // Log file to process and include in the archive - PrimeVersion string // Final version tag - BuildVersion string // Build version from where this release has cut - Bucket string // Bucket we will use to archive and read staged data -} - -// ArchiveBucketPath returns the bucket path we the release will be stored. -func (o *ArchiverOptions) ArchiveBucketPath() string { - // local archive_bucket="gs://$RELEASE_BUCKET/archive" - if o.Bucket == "" || o.PrimeVersion == "" { - return "" - } - gcs := object.NewGCS() - archiveBucketPath, err := gcs.NormalizePath( - object.GcsPrefix + filepath.Join(o.Bucket, ArchivePath, archiveDirPrefix+o.PrimeVersion), - ) - if err != nil { - logrus.Error(err) - return "" - } - return archiveBucketPath -} - -// Validate checks if the set values are correct and complete to -// start running the archival process. -func (o *ArchiverOptions) Validate() error { - if o.LogFile == "" { - return errors.New("release log file was not specified") - } - if !util.Exists(o.ReleaseBuildDir) { - return errors.New("GCB worskapce directory does not exist") - } - if !util.Exists(o.LogFile) { - return errors.New("logs file not found") - } - if o.BuildVersion == "" { - return errors.New("build version tag in archiver options is empty") - } - if o.PrimeVersion == "" { - return errors.New("prime version tag in archiver options is empty") - } - if o.Bucket == "" { - return errors.New("archive bucket is not specified") - } - - // Check if the build version is well formed (used for cleaning old staged build) - if _, err := util.TagStringToSemver(o.BuildVersion); err != nil { - return fmt.Errorf("verifying build version tag: %w", err) - } - - // Check if the prime version is well formed - if _, err := util.TagStringToSemver(o.PrimeVersion); err != nil { - return fmt.Errorf("verifying prime version tag: %w", err) - } - - return nil -} - -//counterfeiter:generate . archiverImpl -type archiverImpl interface { - CopyReleaseToBucket(string, string) error - DeleteStalePasswordFiles(string) error - MakeFilesPrivate(string) error - ValidateOptions(*ArchiverOptions) error - CopyReleaseLogs([]string, string, string) error - CleanStagedBuilds(string, string) error -} - -type defaultArchiverImpl struct{} - -// ArchiveRelease stores the release directory and logs in a GCP -// bucket for archival purposes. Log files are sanitized and made private. -func (archiver *Archiver) ArchiveRelease() error { - // Verify options are complete - if err := archiver.impl.ValidateOptions(archiver.opts); err != nil { - return fmt.Errorf("validating archive options: %w", err) - } - - // TODO: Is this still relevant? - // local text="files" - - // # TODO: Copy $PROGSTATE as well to GCS and restore it if found - // # also delete if complete or just delete once copied back to $TMPDIR - // # This is so failures on GCB can be restarted / reentrant too. - - // if [[ $arg != "--files-only" ]]; then - // dash_args="-rc" - // text="contents" - // fi - - // Remove temporary password file so not to alarm passers-by. - if err := archiver.impl.DeleteStalePasswordFiles( - archiver.opts.ReleaseBuildDir, - ); err != nil { - return fmt.Errorf("looking for stale password files: %w", err) - } - - // Clean previous staged builds - if err := archiver.impl.CleanStagedBuilds( - object.GcsPrefix+filepath.Join(archiver.opts.Bucket, StagePath), - archiver.opts.BuildVersion, - ); err != nil { - return fmt.Errorf("deleting previous staged builds: %w", err) - } - - // Copy the release to the bucket - if err := archiver.impl.CopyReleaseToBucket( - archiver.opts.ReleaseBuildDir, - archiver.opts.ArchiveBucketPath(), - ); err != nil { - return fmt.Errorf("while copying the release directory: %w", err) - } - - // copy_logs_to_workdir - if err := archiver.impl.CopyReleaseLogs( - []string{archiver.opts.LogFile}, - filepath.Join(archiver.opts.ReleaseBuildDir, logsArchiveSubPath), - filepath.Join(archiver.opts.ArchiveBucketPath(), logsArchiveSubPath), - ); err != nil { - return fmt.Errorf("copying release logs to archive: %w", err) - } - - // Make the logs private (remove AllUsers from the GCS ACL) - if err := archiver.impl.MakeFilesPrivate( - filepath.Join(archiver.opts.ArchiveBucketPath(), logsArchiveSubPath), - ); err != nil { - return fmt.Errorf("setting private ACL on logs: %w", err) - } - - logrus.Info("Release archive complete") - return nil -} - -// validateOptions runs the options validation. -func (a *defaultArchiverImpl) ValidateOptions(o *ArchiverOptions) error { - if err := o.Validate(); err != nil { - return fmt.Errorf("validating options: %w", err) - } - return nil -} - -// makeFilesPrivate updates the ACL on all files in a directory. -func (a *defaultArchiverImpl) MakeFilesPrivate(archiveBucketPath string) error { - logrus.Infof("Ensure PRIVATE ACL on %s/*", archiveBucketPath) - gcs := object.NewGCS() - logsPath, err := gcs.NormalizePath(archiveBucketPath + "/*") - if err != nil { - return fmt.Errorf("normalizing gcs path to modify ACL: %w", err) - } - // logrun -s $GSUTIL acl ch -d AllUsers "$archive_bucket/$build_dir/${LOGFILE##*/}*" || true - if err := gcli.GSUtil("acl", "ch", "-d", "AllUsers", logsPath); err != nil { - return fmt.Errorf("removing public access from files in %s: %w", archiveBucketPath, err) - } - return nil -} - -// deleteStalePasswordFiles emoves temporary password file so not to alarm passers-by. -func (a *defaultArchiverImpl) DeleteStalePasswordFiles(releaseBuildDir string) error { - if err := command.NewWithWorkDir( - releaseBuildDir, "find", "-type", "f", "-name", "rsyncd.password", "-delete", - ).RunSuccess(); err != nil { - return fmt.Errorf("deleting temporary password files: %w", err) - } - - // Delete the git remote config to avoid it ending in the stage bucket - gitConf := filepath.Join(releaseBuildDir, "k8s.io", "kubernetes", ".git", "config") - if util.Exists(gitConf) { - if err := os.Remove(gitConf); err != nil { - return fmt.Errorf("deleting git remote config: %w", err) - } - } else { - logrus.Warn("git configuration file not found, nothing to remove") - } - - return nil -} - -// copyReleaseLogs gets a slice of log file names. Those files are -// sanitized to remove sensitive data and control characters and then are -// copied to the GCB working directory. -func (a *defaultArchiverImpl) CopyReleaseLogs( - logFiles []string, targetDir, archiveBucketLogsPath string, -) (err error) { - // Verify the destination bucket address is correct - gcs := object.NewGCS() - if archiveBucketLogsPath != "" { - archiveBucketLogsPath, err = gcs.NormalizePath(archiveBucketLogsPath) - if err != nil { - return fmt.Errorf("normalizing remote logfile destination: %w", err) - } - } - // Check the destination directory exists - if !util.Exists(targetDir) { - if err := os.Mkdir(targetDir, os.FileMode(0o755)); err != nil { - return fmt.Errorf("creating logs archive directory: %w", err) - } - } - for _, fileName := range logFiles { - // Strip the logfiles from control chars and sensitive data - if err := util.CleanLogFile(fileName); err != nil { - return fmt.Errorf("sanitizing logfile: %w", err) - } - - logrus.Infof("Copying %s to %s", fileName, targetDir) - if err := util.CopyFileLocal( - fileName, filepath.Join(targetDir, filepath.Base(fileName)), true, - ); err != nil { - return fmt.Errorf("copying logfile %s to %s: %w", fileName, targetDir, err) - } - } - // TODO: Grab previous log files from stage and copy them to logs dir - - // Rsync log files to remote location if a bucket is specified - if archiveBucketLogsPath != "" { - logrus.Infof("Rsyncing logs to remote bucket %s", archiveBucketLogsPath) - if err := gcs.RsyncRecursive(targetDir, archiveBucketLogsPath); err != nil { - return fmt.Errorf("while synching log files to remote bucket addr: %w", err) - } - } - return nil -} - -// copyReleaseToBucket Copies the release directory to the specified bucket location. -func (a *defaultArchiverImpl) CopyReleaseToBucket(releaseBuildDir, archiveBucketPath string) error { - // TODO: Check if we have write access to the bucket? - - // Create a GCS client to copy the release - gcs := object.NewGCS() - remoteDest, err := gcs.NormalizePath(archiveBucketPath) - if err != nil { - return fmt.Errorf("normalizing destination path: %w", err) - } - - srcPath := filepath.Join(releaseBuildDir, "k8s.io") - tarball := srcPath + ".tar.gz" - logrus.Infof("Compressing %s to %s", srcPath, tarball) - if err := tar.Compress(tarball, srcPath); err != nil { - return fmt.Errorf("create source tarball: %w", err) - } - - logrus.Infof("Removing source path %s before syncing", srcPath) - if err := os.RemoveAll(srcPath); err != nil { - return fmt.Errorf("remove source path: %w", err) - } - - logrus.Infof("Rsync %s to %s", releaseBuildDir, remoteDest) - if err := gcs.RsyncRecursive(releaseBuildDir, remoteDest); err != nil { - return fmt.Errorf("copying release directory to bucket: %w", err) - } - return nil -} - -// GetLogFiles reads a directory and returns the files that are anago logs. -func (a *defaultArchiverImpl) GetLogFiles(logsDir string) ([]string, error) { - logFiles := []string{} - tmpContents, err := os.ReadDir(logsDir) - if err != nil { - return nil, fmt.Errorf("searching for logfiles in %s: %w", logsDir, err) - } - for _, finfo := range tmpContents { - if strings.HasPrefix(finfo.Name(), "anago") && - strings.Contains(finfo.Name(), ".log") { - logFiles = append(logFiles, filepath.Join(logsDir, finfo.Name())) - } - } - return logFiles, nil -} - -// CleanStagedBuilds removes all past staged builds from the same -// Major.Minor version we are running now. -func (a *defaultArchiverImpl) CleanStagedBuilds(bucketPath, buildVersion string) error { - // Build the prefix we will be looking for - semver, err := util.TagStringToSemver(buildVersion) - if err != nil { - return fmt.Errorf("parsing semver from tag: %w", err) - } - dirPrefix := fmt.Sprintf("%s%d.%d", util.TagPrefix, semver.Major, semver.Minor) - - // Normalize the bucket parh - // Build a GCS object to delete old builds - gcs := object.NewGCS() - gcs.SetOptions( - gcs.WithConcurrent(true), - gcs.WithRecursive(true), - ) - - // Normalize the bucket path - path, err := gcs.NormalizePath(bucketPath, dirPrefix+"*") - if err != nil { - return fmt.Errorf("normalizing stage path: %w", err) - } - - // Get all staged build that match the pattern - output, err := gcli.GSUtilOutput("ls", "-d", path) - if err != nil { - return fmt.Errorf("listing bucket contents: %w", err) - } - - for _, line := range strings.Fields(output) { - if strings.Contains(line, dirPrefix) && !strings.Contains(line, buildVersion) { - logrus.Infof("Deleting previous staged build: %s", line) - if err := gcs.DeletePath(line); err != nil { - return fmt.Errorf("calling gsutil to delete build: %w", err) - } - } - } - return nil -} diff --git a/pkg/release/archive_test.go b/pkg/release/archive_test.go deleted file mode 100644 index f73f8b3610e..00000000000 --- a/pkg/release/archive_test.go +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2020 The Kubernetes 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 release_test - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/require" - - "k8s.io/release/pkg/release" - "k8s.io/release/pkg/release/releasefakes" -) - -func TestArchiveRelease(t *testing.T) { - err := errors.New("Synthetic error") - for _, tc := range []struct { - prepare func(*releasefakes.FakeArchiverImpl) - shouldErr bool - }{ - { // Default: Success - prepare: func(mock *releasefakes.FakeArchiverImpl) {}, - shouldErr: false, - }, - { // failure Validate options fails - prepare: func(mock *releasefakes.FakeArchiverImpl) { - mock.ValidateOptionsReturns(err) - }, - shouldErr: true, - }, - { // failure CopyReleaseLogsReturns errors - prepare: func(mock *releasefakes.FakeArchiverImpl) { - mock.CopyReleaseLogsReturns(err) - }, - shouldErr: true, - }, - { // failure CopyReleaseToBucket fails - prepare: func(mock *releasefakes.FakeArchiverImpl) { - mock.CopyReleaseToBucketReturns(err) - }, - shouldErr: true, - }, - { // failure CopyReleaseToBucket fails - prepare: func(mock *releasefakes.FakeArchiverImpl) { - mock.MakeFilesPrivateReturns(err) - }, - shouldErr: true, - }, - { // CleanStagedBuilds fails - prepare: func(mock *releasefakes.FakeArchiverImpl) { - mock.CleanStagedBuildsReturns(err) - }, - shouldErr: true, - }, - } { - mock := &releasefakes.FakeArchiverImpl{} - sut := release.NewArchiver(&release.ArchiverOptions{}) - tc.prepare(mock) - sut.SetImpl(mock) - - err := sut.ArchiveRelease() - if tc.shouldErr { - require.NotNil(t, err) - } else { - require.Nil(t, err) - } - } -} diff --git a/pkg/release/archive_unit_test.go b/pkg/release/archive_unit_test.go deleted file mode 100644 index b374f501ffc..00000000000 --- a/pkg/release/archive_unit_test.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright 2020 The Kubernetes 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 release - -import ( - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" - - "sigs.k8s.io/release-sdk/object" -) - -const fictionalTestBucketName = "kubernetes-test-name" - -func TestCopyReleaseLogsToWorkDir(t *testing.T) { - // create two files to simulate logs - tmp1, err := os.CreateTemp("", "test-copylogs-") - require.Nil(t, err) - defer os.Remove(tmp1.Name()) - tmp2, err := os.CreateTemp("", "test-copylogs-") - require.Nil(t, err) - defer os.Remove(tmp2.Name()) - - // Create a target directory to copy the files - destDir, err := os.MkdirTemp("", "test-move-logs") - require.Nil(t, err, "creating test dir") - defer os.RemoveAll(destDir) - - // Put an oauth token in the first log - content1 := "7aa33bd2186c40840c4c2df321241e241def98ca:x-oauth-basic\n" - require.Nil(t, os.WriteFile( - tmp1.Name(), []byte(content1), os.FileMode(0o644), - )) - - // Write a regular text in the second - content2 := "Hello world!\n" - require.Nil(t, os.WriteFile( - tmp2.Name(), []byte(content2), os.FileMode(0o644), - )) - - // Create the implementation - impl := &defaultArchiverImpl{} - // Copy the log files to the mock directory - err = impl.CopyReleaseLogs([]string{tmp1.Name(), tmp2.Name()}, destDir, "") - require.Nil(t, err) - - // Reopoen the files to check them - movedData1, err := os.ReadFile(filepath.Join(destDir, filepath.Base(tmp1.Name()))) - require.Nil(t, err) - - movedData2, err := os.ReadFile(filepath.Join(destDir, filepath.Base(tmp2.Name()))) - require.Nil(t, err) - - // The first file should be sanitized. Should differ - require.NotEmpty(t, movedData1) - require.NotEqual(t, content1, string(movedData1)) - - // The second file should be the same. - require.Equal(t, content2, string(movedData2)) -} - -func TestArchiveBucketPath(t *testing.T) { - // By default, the bucket name is empty, resulting in an empty - // GCS URI. This is to avoid getting a wrong but valid bucket location - DefaultArchiveOptions := &ArchiverOptions{} - require.Empty(t, DefaultArchiveOptions.ArchiveBucketPath()) - - // Using a bucket name should return a valid URI - opts := ArchiverOptions{ - // Here, we test without "gs://", the gcs package should - // normalize the location with or without - Bucket: fictionalTestBucketName, - PrimeVersion: "v1.20.0-beta.2", - } - require.Equal(t, - object.GcsPrefix+filepath.Join(fictionalTestBucketName, archiveBucketPath, archiveDirPrefix+opts.PrimeVersion), - opts.ArchiveBucketPath(), - ) -} - -func TestValidateOpts(t *testing.T) { - testOpts := &ArchiverOptions{} - - // An empty options struct should not validate: - require.NotNil(t, testOpts.Validate()) - - // Create a fake directory to test - dir, err := os.MkdirTemp("", "archiver-opts-test-") - require.Nil(t, err) - defer os.RemoveAll(dir) - - // With complete values, still should not validate as most - // directories do not exist - testOpts.Bucket = "kubernetes-test-name" - testOpts.PrimeVersion = "v1.20.0-beta.1" - testOpts.BuildVersion = "v1.20.0-beta.0.80+cdfd82733af78c" - testOpts.ReleaseBuildDir = filepath.Join(dir, testOpts.BuildVersion) - require.NotNil(t, testOpts.Validate()) - - // Creating a test log (/workdir/tmp) should still not - // validate, build dir is missing - tmplog, err := os.CreateTemp("", "anago-test-log-") - require.Nil(t, err) - testOpts.LogFile = tmplog.Name() - require.NotNil(t, testOpts.Validate()) - - // Finally create the build dir and we're done - require.Nil(t, os.Mkdir(testOpts.ReleaseBuildDir, os.FileMode(0o755))) - - // Should succeed - require.Nil(t, testOpts.Validate()) -} - -func TestGetLogFiles(t *testing.T) { - dir, err := os.MkdirTemp("", "test-get-anago-logs") - require.Nil(t, err, "creating test dir") - defer os.RemoveAll(dir) - - goodFiles := []string{"anago.log", "anago-stage.log", "anago.log.1", "anago-stage.log.1"} - allFiles := goodFiles - allFiles = append(allFiles, "test1.txt", "other.log", "anago.txt") - for _, fileName := range allFiles { - require.Nil(t, os.WriteFile(filepath.Join(dir, fileName), []byte("test"), os.FileMode(0o644))) - } - impl := &defaultArchiverImpl{} - foundPaths, err := impl.GetLogFiles(dir) - foundFilenames := []string{} - for _, logFile := range foundPaths { - foundFilenames = append(foundFilenames, filepath.Base(logFile)) - } - require.Nil(t, err) - require.ElementsMatch(t, goodFiles, foundFilenames) -} - -func TestDeleteStalePasswordFiles(t *testing.T) { - dir, err := os.MkdirTemp("", "test-delete-stale-pw-") - require.Nil(t, err, "creating test dir") - defer os.RemoveAll(dir) - - // Create temporary files - require.Nil(t, os.WriteFile(filepath.Join(dir, "test.txt"), []byte("Hello World"), os.FileMode(0o644))) - require.Nil(t, os.WriteFile(filepath.Join(dir, "rsyncd.password"), []byte("Hello World"), os.FileMode(0o644))) - - // Run the pass clear - impl := &defaultArchiverImpl{} - err = impl.DeleteStalePasswordFiles(dir) - require.Nil(t, err) - - // Check that the pw file is gone while the other files remained - require.FileExists(t, filepath.Join(dir, "test.txt")) - require.NoFileExists(t, filepath.Join(dir, "rsyncd.password")) -} diff --git a/pkg/release/doc.go b/pkg/release/doc.go index 41785fd98fc..453de79faa0 100644 --- a/pkg/release/doc.go +++ b/pkg/release/doc.go @@ -23,4 +23,3 @@ package release //go:generate /usr/bin/env bash -c "cat ../../hack/boilerplate/boilerplate.generatego.txt releasefakes/fake_prerequisites_checker_impl.go > releasefakes/_fake_prerequisites_checker_impl.go && mv releasefakes/_fake_prerequisites_checker_impl.go releasefakes/fake_prerequisites_checker_impl.go" //go:generate /usr/bin/env bash -c "cat ../../hack/boilerplate/boilerplate.generatego.txt releasefakes/fake_image_impl.go > releasefakes/_fake_image_impl.go && mv releasefakes/_fake_image_impl.go releasefakes/fake_image_impl.go" //go:generate /usr/bin/env bash -c "cat ../../hack/boilerplate/boilerplate.generatego.txt releasefakes/fake_branch_checker_impl.go > releasefakes/_fake_branch_checker_impl.go && mv releasefakes/_fake_branch_checker_impl.go releasefakes/fake_branch_checker_impl.go" -//go:generate /usr/bin/env bash -c "cat ../../hack/boilerplate/boilerplate.generatego.txt releasefakes/fake_archiver_impl.go > releasefakes/_fake_archiver_impl.go && mv releasefakes/_fake_archiver_impl.go releasefakes/fake_archiver_impl.go" diff --git a/pkg/release/release.go b/pkg/release/release.go index 0a422417305..ed40f149972 100644 --- a/pkg/release/release.go +++ b/pkg/release/release.go @@ -126,9 +126,6 @@ const ( // The default bazel build directory. BazelBuildDir = "bazel-bin/build" - // Archive path is the root path in the bucket where releases are archived. - ArchivePath = "archive" - // Publishing bot issue repository. PubBotRepoOrg = "kubernetes" PubBotRepoName = "sig-release" diff --git a/pkg/release/releasefakes/fake_archiver_impl.go b/pkg/release/releasefakes/fake_archiver_impl.go deleted file mode 100644 index b8551eee3a8..00000000000 --- a/pkg/release/releasefakes/fake_archiver_impl.go +++ /dev/null @@ -1,508 +0,0 @@ -/* -Copyright The Kubernetes 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. -*/ - -// Code generated by counterfeiter. DO NOT EDIT. -package releasefakes - -import ( - "sync" - - "k8s.io/release/pkg/release" -) - -type FakeArchiverImpl struct { - CleanStagedBuildsStub func(string, string) error - cleanStagedBuildsMutex sync.RWMutex - cleanStagedBuildsArgsForCall []struct { - arg1 string - arg2 string - } - cleanStagedBuildsReturns struct { - result1 error - } - cleanStagedBuildsReturnsOnCall map[int]struct { - result1 error - } - CopyReleaseLogsStub func([]string, string, string) error - copyReleaseLogsMutex sync.RWMutex - copyReleaseLogsArgsForCall []struct { - arg1 []string - arg2 string - arg3 string - } - copyReleaseLogsReturns struct { - result1 error - } - copyReleaseLogsReturnsOnCall map[int]struct { - result1 error - } - CopyReleaseToBucketStub func(string, string) error - copyReleaseToBucketMutex sync.RWMutex - copyReleaseToBucketArgsForCall []struct { - arg1 string - arg2 string - } - copyReleaseToBucketReturns struct { - result1 error - } - copyReleaseToBucketReturnsOnCall map[int]struct { - result1 error - } - DeleteStalePasswordFilesStub func(string) error - deleteStalePasswordFilesMutex sync.RWMutex - deleteStalePasswordFilesArgsForCall []struct { - arg1 string - } - deleteStalePasswordFilesReturns struct { - result1 error - } - deleteStalePasswordFilesReturnsOnCall map[int]struct { - result1 error - } - MakeFilesPrivateStub func(string) error - makeFilesPrivateMutex sync.RWMutex - makeFilesPrivateArgsForCall []struct { - arg1 string - } - makeFilesPrivateReturns struct { - result1 error - } - makeFilesPrivateReturnsOnCall map[int]struct { - result1 error - } - ValidateOptionsStub func(*release.ArchiverOptions) error - validateOptionsMutex sync.RWMutex - validateOptionsArgsForCall []struct { - arg1 *release.ArchiverOptions - } - validateOptionsReturns struct { - result1 error - } - validateOptionsReturnsOnCall map[int]struct { - result1 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *FakeArchiverImpl) CleanStagedBuilds(arg1 string, arg2 string) error { - fake.cleanStagedBuildsMutex.Lock() - ret, specificReturn := fake.cleanStagedBuildsReturnsOnCall[len(fake.cleanStagedBuildsArgsForCall)] - fake.cleanStagedBuildsArgsForCall = append(fake.cleanStagedBuildsArgsForCall, struct { - arg1 string - arg2 string - }{arg1, arg2}) - stub := fake.CleanStagedBuildsStub - fakeReturns := fake.cleanStagedBuildsReturns - fake.recordInvocation("CleanStagedBuilds", []interface{}{arg1, arg2}) - fake.cleanStagedBuildsMutex.Unlock() - if stub != nil { - return stub(arg1, arg2) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeArchiverImpl) CleanStagedBuildsCallCount() int { - fake.cleanStagedBuildsMutex.RLock() - defer fake.cleanStagedBuildsMutex.RUnlock() - return len(fake.cleanStagedBuildsArgsForCall) -} - -func (fake *FakeArchiverImpl) CleanStagedBuildsCalls(stub func(string, string) error) { - fake.cleanStagedBuildsMutex.Lock() - defer fake.cleanStagedBuildsMutex.Unlock() - fake.CleanStagedBuildsStub = stub -} - -func (fake *FakeArchiverImpl) CleanStagedBuildsArgsForCall(i int) (string, string) { - fake.cleanStagedBuildsMutex.RLock() - defer fake.cleanStagedBuildsMutex.RUnlock() - argsForCall := fake.cleanStagedBuildsArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *FakeArchiverImpl) CleanStagedBuildsReturns(result1 error) { - fake.cleanStagedBuildsMutex.Lock() - defer fake.cleanStagedBuildsMutex.Unlock() - fake.CleanStagedBuildsStub = nil - fake.cleanStagedBuildsReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) CleanStagedBuildsReturnsOnCall(i int, result1 error) { - fake.cleanStagedBuildsMutex.Lock() - defer fake.cleanStagedBuildsMutex.Unlock() - fake.CleanStagedBuildsStub = nil - if fake.cleanStagedBuildsReturnsOnCall == nil { - fake.cleanStagedBuildsReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.cleanStagedBuildsReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) CopyReleaseLogs(arg1 []string, arg2 string, arg3 string) error { - var arg1Copy []string - if arg1 != nil { - arg1Copy = make([]string, len(arg1)) - copy(arg1Copy, arg1) - } - fake.copyReleaseLogsMutex.Lock() - ret, specificReturn := fake.copyReleaseLogsReturnsOnCall[len(fake.copyReleaseLogsArgsForCall)] - fake.copyReleaseLogsArgsForCall = append(fake.copyReleaseLogsArgsForCall, struct { - arg1 []string - arg2 string - arg3 string - }{arg1Copy, arg2, arg3}) - stub := fake.CopyReleaseLogsStub - fakeReturns := fake.copyReleaseLogsReturns - fake.recordInvocation("CopyReleaseLogs", []interface{}{arg1Copy, arg2, arg3}) - fake.copyReleaseLogsMutex.Unlock() - if stub != nil { - return stub(arg1, arg2, arg3) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeArchiverImpl) CopyReleaseLogsCallCount() int { - fake.copyReleaseLogsMutex.RLock() - defer fake.copyReleaseLogsMutex.RUnlock() - return len(fake.copyReleaseLogsArgsForCall) -} - -func (fake *FakeArchiverImpl) CopyReleaseLogsCalls(stub func([]string, string, string) error) { - fake.copyReleaseLogsMutex.Lock() - defer fake.copyReleaseLogsMutex.Unlock() - fake.CopyReleaseLogsStub = stub -} - -func (fake *FakeArchiverImpl) CopyReleaseLogsArgsForCall(i int) ([]string, string, string) { - fake.copyReleaseLogsMutex.RLock() - defer fake.copyReleaseLogsMutex.RUnlock() - argsForCall := fake.copyReleaseLogsArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 -} - -func (fake *FakeArchiverImpl) CopyReleaseLogsReturns(result1 error) { - fake.copyReleaseLogsMutex.Lock() - defer fake.copyReleaseLogsMutex.Unlock() - fake.CopyReleaseLogsStub = nil - fake.copyReleaseLogsReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) CopyReleaseLogsReturnsOnCall(i int, result1 error) { - fake.copyReleaseLogsMutex.Lock() - defer fake.copyReleaseLogsMutex.Unlock() - fake.CopyReleaseLogsStub = nil - if fake.copyReleaseLogsReturnsOnCall == nil { - fake.copyReleaseLogsReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.copyReleaseLogsReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) CopyReleaseToBucket(arg1 string, arg2 string) error { - fake.copyReleaseToBucketMutex.Lock() - ret, specificReturn := fake.copyReleaseToBucketReturnsOnCall[len(fake.copyReleaseToBucketArgsForCall)] - fake.copyReleaseToBucketArgsForCall = append(fake.copyReleaseToBucketArgsForCall, struct { - arg1 string - arg2 string - }{arg1, arg2}) - stub := fake.CopyReleaseToBucketStub - fakeReturns := fake.copyReleaseToBucketReturns - fake.recordInvocation("CopyReleaseToBucket", []interface{}{arg1, arg2}) - fake.copyReleaseToBucketMutex.Unlock() - if stub != nil { - return stub(arg1, arg2) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeArchiverImpl) CopyReleaseToBucketCallCount() int { - fake.copyReleaseToBucketMutex.RLock() - defer fake.copyReleaseToBucketMutex.RUnlock() - return len(fake.copyReleaseToBucketArgsForCall) -} - -func (fake *FakeArchiverImpl) CopyReleaseToBucketCalls(stub func(string, string) error) { - fake.copyReleaseToBucketMutex.Lock() - defer fake.copyReleaseToBucketMutex.Unlock() - fake.CopyReleaseToBucketStub = stub -} - -func (fake *FakeArchiverImpl) CopyReleaseToBucketArgsForCall(i int) (string, string) { - fake.copyReleaseToBucketMutex.RLock() - defer fake.copyReleaseToBucketMutex.RUnlock() - argsForCall := fake.copyReleaseToBucketArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *FakeArchiverImpl) CopyReleaseToBucketReturns(result1 error) { - fake.copyReleaseToBucketMutex.Lock() - defer fake.copyReleaseToBucketMutex.Unlock() - fake.CopyReleaseToBucketStub = nil - fake.copyReleaseToBucketReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) CopyReleaseToBucketReturnsOnCall(i int, result1 error) { - fake.copyReleaseToBucketMutex.Lock() - defer fake.copyReleaseToBucketMutex.Unlock() - fake.CopyReleaseToBucketStub = nil - if fake.copyReleaseToBucketReturnsOnCall == nil { - fake.copyReleaseToBucketReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.copyReleaseToBucketReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) DeleteStalePasswordFiles(arg1 string) error { - fake.deleteStalePasswordFilesMutex.Lock() - ret, specificReturn := fake.deleteStalePasswordFilesReturnsOnCall[len(fake.deleteStalePasswordFilesArgsForCall)] - fake.deleteStalePasswordFilesArgsForCall = append(fake.deleteStalePasswordFilesArgsForCall, struct { - arg1 string - }{arg1}) - stub := fake.DeleteStalePasswordFilesStub - fakeReturns := fake.deleteStalePasswordFilesReturns - fake.recordInvocation("DeleteStalePasswordFiles", []interface{}{arg1}) - fake.deleteStalePasswordFilesMutex.Unlock() - if stub != nil { - return stub(arg1) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeArchiverImpl) DeleteStalePasswordFilesCallCount() int { - fake.deleteStalePasswordFilesMutex.RLock() - defer fake.deleteStalePasswordFilesMutex.RUnlock() - return len(fake.deleteStalePasswordFilesArgsForCall) -} - -func (fake *FakeArchiverImpl) DeleteStalePasswordFilesCalls(stub func(string) error) { - fake.deleteStalePasswordFilesMutex.Lock() - defer fake.deleteStalePasswordFilesMutex.Unlock() - fake.DeleteStalePasswordFilesStub = stub -} - -func (fake *FakeArchiverImpl) DeleteStalePasswordFilesArgsForCall(i int) string { - fake.deleteStalePasswordFilesMutex.RLock() - defer fake.deleteStalePasswordFilesMutex.RUnlock() - argsForCall := fake.deleteStalePasswordFilesArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeArchiverImpl) DeleteStalePasswordFilesReturns(result1 error) { - fake.deleteStalePasswordFilesMutex.Lock() - defer fake.deleteStalePasswordFilesMutex.Unlock() - fake.DeleteStalePasswordFilesStub = nil - fake.deleteStalePasswordFilesReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) DeleteStalePasswordFilesReturnsOnCall(i int, result1 error) { - fake.deleteStalePasswordFilesMutex.Lock() - defer fake.deleteStalePasswordFilesMutex.Unlock() - fake.DeleteStalePasswordFilesStub = nil - if fake.deleteStalePasswordFilesReturnsOnCall == nil { - fake.deleteStalePasswordFilesReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.deleteStalePasswordFilesReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) MakeFilesPrivate(arg1 string) error { - fake.makeFilesPrivateMutex.Lock() - ret, specificReturn := fake.makeFilesPrivateReturnsOnCall[len(fake.makeFilesPrivateArgsForCall)] - fake.makeFilesPrivateArgsForCall = append(fake.makeFilesPrivateArgsForCall, struct { - arg1 string - }{arg1}) - stub := fake.MakeFilesPrivateStub - fakeReturns := fake.makeFilesPrivateReturns - fake.recordInvocation("MakeFilesPrivate", []interface{}{arg1}) - fake.makeFilesPrivateMutex.Unlock() - if stub != nil { - return stub(arg1) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeArchiverImpl) MakeFilesPrivateCallCount() int { - fake.makeFilesPrivateMutex.RLock() - defer fake.makeFilesPrivateMutex.RUnlock() - return len(fake.makeFilesPrivateArgsForCall) -} - -func (fake *FakeArchiverImpl) MakeFilesPrivateCalls(stub func(string) error) { - fake.makeFilesPrivateMutex.Lock() - defer fake.makeFilesPrivateMutex.Unlock() - fake.MakeFilesPrivateStub = stub -} - -func (fake *FakeArchiverImpl) MakeFilesPrivateArgsForCall(i int) string { - fake.makeFilesPrivateMutex.RLock() - defer fake.makeFilesPrivateMutex.RUnlock() - argsForCall := fake.makeFilesPrivateArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeArchiverImpl) MakeFilesPrivateReturns(result1 error) { - fake.makeFilesPrivateMutex.Lock() - defer fake.makeFilesPrivateMutex.Unlock() - fake.MakeFilesPrivateStub = nil - fake.makeFilesPrivateReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) MakeFilesPrivateReturnsOnCall(i int, result1 error) { - fake.makeFilesPrivateMutex.Lock() - defer fake.makeFilesPrivateMutex.Unlock() - fake.MakeFilesPrivateStub = nil - if fake.makeFilesPrivateReturnsOnCall == nil { - fake.makeFilesPrivateReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.makeFilesPrivateReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) ValidateOptions(arg1 *release.ArchiverOptions) error { - fake.validateOptionsMutex.Lock() - ret, specificReturn := fake.validateOptionsReturnsOnCall[len(fake.validateOptionsArgsForCall)] - fake.validateOptionsArgsForCall = append(fake.validateOptionsArgsForCall, struct { - arg1 *release.ArchiverOptions - }{arg1}) - stub := fake.ValidateOptionsStub - fakeReturns := fake.validateOptionsReturns - fake.recordInvocation("ValidateOptions", []interface{}{arg1}) - fake.validateOptionsMutex.Unlock() - if stub != nil { - return stub(arg1) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *FakeArchiverImpl) ValidateOptionsCallCount() int { - fake.validateOptionsMutex.RLock() - defer fake.validateOptionsMutex.RUnlock() - return len(fake.validateOptionsArgsForCall) -} - -func (fake *FakeArchiverImpl) ValidateOptionsCalls(stub func(*release.ArchiverOptions) error) { - fake.validateOptionsMutex.Lock() - defer fake.validateOptionsMutex.Unlock() - fake.ValidateOptionsStub = stub -} - -func (fake *FakeArchiverImpl) ValidateOptionsArgsForCall(i int) *release.ArchiverOptions { - fake.validateOptionsMutex.RLock() - defer fake.validateOptionsMutex.RUnlock() - argsForCall := fake.validateOptionsArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeArchiverImpl) ValidateOptionsReturns(result1 error) { - fake.validateOptionsMutex.Lock() - defer fake.validateOptionsMutex.Unlock() - fake.ValidateOptionsStub = nil - fake.validateOptionsReturns = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) ValidateOptionsReturnsOnCall(i int, result1 error) { - fake.validateOptionsMutex.Lock() - defer fake.validateOptionsMutex.Unlock() - fake.ValidateOptionsStub = nil - if fake.validateOptionsReturnsOnCall == nil { - fake.validateOptionsReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.validateOptionsReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *FakeArchiverImpl) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.cleanStagedBuildsMutex.RLock() - defer fake.cleanStagedBuildsMutex.RUnlock() - fake.copyReleaseLogsMutex.RLock() - defer fake.copyReleaseLogsMutex.RUnlock() - fake.copyReleaseToBucketMutex.RLock() - defer fake.copyReleaseToBucketMutex.RUnlock() - fake.deleteStalePasswordFilesMutex.RLock() - defer fake.deleteStalePasswordFilesMutex.RUnlock() - fake.makeFilesPrivateMutex.RLock() - defer fake.makeFilesPrivateMutex.RUnlock() - fake.validateOptionsMutex.RLock() - defer fake.validateOptionsMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *FakeArchiverImpl) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -}