-
Notifications
You must be signed in to change notification settings - Fork 49
Migrate to Structured Logging with zerolog and Improve Logging for Manifest Purge Logic #473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 5 commits
8910185
f1a3997
009bb50
6fcf423
12c3f19
42e878c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,4 +5,5 @@ | |
| coverage.txt | ||
| *.test | ||
| *.out | ||
| *.html | ||
| *.html | ||
| acr-bin | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ import ( | |
|
|
||
| "github.com/Azure/acr-cli/cmd/common" | ||
| "github.com/Azure/acr-cli/internal/api" | ||
| "github.com/Azure/acr-cli/internal/logger" | ||
| "github.com/Azure/acr-cli/internal/worker" | ||
| "github.com/dlclark/regexp2" | ||
| "github.com/spf13/cobra" | ||
|
|
@@ -163,8 +164,17 @@ func annotateTags(ctx context.Context, | |
| dryRun bool) (int, error) { | ||
|
|
||
| if !dryRun { | ||
| log := logger.Get() | ||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Msg("Starting tag annotation for repository") | ||
| fmt.Printf("\nAnnotating tags for repository: %s\n", repoName) | ||
| } else { | ||
| log := logger.Get() | ||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Bool("dry_run", true). | ||
| Msg("Dry run: would annotate tags for repository") | ||
| fmt.Printf("\nTags for this repository would be annotated: %s\n", repoName) | ||
| } | ||
|
|
||
|
|
@@ -225,6 +235,11 @@ func getManifestsToAnnotate(ctx context.Context, | |
| resultTags, err := acrClient.GetAcrTags(ctx, repoName, "timedesc", lastTag) | ||
| if err != nil { | ||
| if resultTags != nil && resultTags.Response.Response != nil && resultTags.StatusCode == http.StatusNotFound { | ||
| log := logger.Get() | ||
| log.Warn(). | ||
| Str("repository", repoName). | ||
| Int("status_code", resultTags.StatusCode). | ||
| Msg("Repository not found during annotation operation") | ||
| fmt.Printf("%s repository not found\n", repoName) | ||
|
||
| return nil, "", nil | ||
| } | ||
|
|
@@ -257,6 +272,12 @@ func getManifestsToAnnotate(ctx context.Context, | |
| // Only print what would be annotated during a dry-run. Successfully annotated manifests | ||
| // will be logged after the annotation. | ||
| if dryRun { | ||
| log := logger.Get() | ||
| log.Debug(). | ||
| Str("repository", repoName). | ||
| Str("tag", *tag.Name). | ||
| Str("manifest", *tag.Digest). | ||
| Msg("Tag marked for annotation in dry run") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should use Bool("dry_run", true)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed to use Bool("dry_run", true) instead of string format. Changes in commit 42e878c. |
||
| fmt.Printf("%s/%s:%s\n", loginURL, repoName, *tag.Name) | ||
| } | ||
| manifestsToAnnotate = append(manifestsToAnnotate, *tag.Digest) | ||
|
|
@@ -280,8 +301,17 @@ func annotateUntaggedManifests(ctx context.Context, | |
| annotations []string, | ||
| dryRun bool) (int, error) { | ||
| if !dryRun { | ||
| log := logger.Get() | ||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Msg("Starting manifest annotation for repository") | ||
| fmt.Printf("Annotating manifests for repository: %s\n", repoName) | ||
| } else { | ||
| log := logger.Get() | ||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Bool("dry_run", true). | ||
| Msg("Dry run: would annotate manifests for repository") | ||
| fmt.Printf("Manifests for this repository would be annotated: %s\n", repoName) | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ import ( | |
| "fmt" | ||
|
|
||
| "github.com/Azure/acr-cli/internal/api" | ||
| "github.com/Azure/acr-cli/internal/logger" | ||
| "github.com/pkg/errors" | ||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
@@ -83,29 +84,56 @@ func newManifestListCmd(manifestParams *manifestParameters) *cobra.Command { | |
|
|
||
| // listManifests will do the http requests and print the digest of all the manifest in the selected repository. | ||
| func listManifests(ctx context.Context, acrClient api.AcrCLIClientInterface, loginURL string, repoName string) error { | ||
| log := logger.Get() | ||
|
|
||
| log.Debug(). | ||
| Str("repository", repoName). | ||
|
||
| Msg("Starting manifest listing") | ||
|
|
||
| lastManifestDigest := "" | ||
| resultManifests, err := acrClient.GetAcrManifests(ctx, repoName, "", lastManifestDigest) | ||
| if err != nil { | ||
| log.Error(). | ||
| Err(err). | ||
| Str("repository", repoName). | ||
| Msg("Failed to get manifests for listing") | ||
| return errors.Wrap(err, "failed to list manifests") | ||
| } | ||
|
|
||
| fmt.Printf("Listing manifests for the %q repository:\n", repoName) | ||
|
|
||
| totalManifests := 0 | ||
| // A for loop is used because the GetAcrManifests method returns by default only 100 manifests and their attributes. | ||
| for resultManifests != nil && resultManifests.ManifestsAttributes != nil { | ||
| manifests := *resultManifests.ManifestsAttributes | ||
| for _, manifest := range manifests { | ||
| manifestDigest := *manifest.Digest | ||
| fmt.Printf("%s/%s@%s\n", loginURL, repoName, manifestDigest) | ||
|
|
||
| log.Debug(). | ||
| Str("repository", repoName). | ||
| Str("manifest", manifestDigest). | ||
| Msg("Listed manifest") | ||
| totalManifests++ | ||
| } | ||
| // Since the GetAcrManifests supports pagination when supplied with the last digest that was returned the last manifest | ||
| // digest is saved, the manifest array contains at least one element because if it was empty the API would return | ||
| // a nil pointer instead of a pointer to a length 0 array. | ||
| lastManifestDigest = *manifests[len(manifests)-1].Digest | ||
| resultManifests, err = acrClient.GetAcrManifests(ctx, repoName, "", lastManifestDigest) | ||
| if err != nil { | ||
| log.Error(). | ||
|
||
| Err(err). | ||
| Str("repository", repoName). | ||
| Msg("Failed to get next page of manifests") | ||
| return errors.Wrap(err, "failed to list manifests") | ||
| } | ||
| } | ||
|
|
||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Int("total_manifests", totalManifests). | ||
| Msg("Completed manifest listing") | ||
| return nil | ||
| } | ||
|
|
||
|
|
@@ -140,13 +168,41 @@ func newManifestDeleteCmd(manifestParams *manifestParameters) *cobra.Command { | |
|
|
||
| // deleteManifests receives an array of manifests digest and deletes them using the supplied acrClient. | ||
| func deleteManifests(ctx context.Context, acrClient api.AcrCLIClientInterface, loginURL string, repoName string, args []string) error { | ||
| log := logger.Get() | ||
|
|
||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Int("manifest_count", len(args)). | ||
| Msg("Starting manifest deletion") | ||
|
|
||
| for i := 0; i < len(args); i++ { | ||
| _, err := acrClient.DeleteManifest(ctx, repoName, args[i]) | ||
| if err != nil { | ||
| log.Error(). | ||
| Err(err). | ||
| Str("repository", repoName). | ||
| Str("manifest", args[i]). | ||
| Int("position", i+1). | ||
| Int("total", len(args)). | ||
| Msg("Failed to delete manifest") | ||
| // If there is an error (this includes not found and not allowed operations) the deletion of the images is stopped and an error is returned. | ||
| return errors.Wrap(err, "failed to delete manifests") | ||
| } | ||
|
|
||
| fmt.Printf("%s/%s@%s\n", loginURL, repoName, args[i]) | ||
|
|
||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Str("manifest", args[i]). | ||
| Str("ref", fmt.Sprintf("%s/%s@%s", loginURL, repoName, args[i])). | ||
| Int("position", i+1). | ||
| Int("total", len(args)). | ||
| Msg("Successfully deleted manifest") | ||
| } | ||
|
|
||
| log.Info(). | ||
| Str("repository", repoName). | ||
| Int("deleted_count", len(args)). | ||
| Msg("Completed manifest deletion") | ||
| return nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this constant logger.Get() . The logger should be acquired once at the top of the function and then used as required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed logger.Get() usage pattern - now acquiring logger once at function top instead of repeated calls. Changes in commit 42e878c.