in cmd/acr/annotate.go [58:150]
func newAnnotateCmd(rootParams *rootParameters) *cobra.Command {
annotateParams := annotateParameters{rootParameters: rootParams}
cmd := &cobra.Command{
Use: "annotate",
Short: "[Preview] Annotate images in a registry",
Long: newAnnotateCmdLongMessage,
Example: annotateExampleMessage,
RunE: func(_ *cobra.Command, _ []string) error {
// This context is used for all the http requests
ctx := context.Background()
registryName, err := annotateParams.GetRegistryName()
if err != nil {
return err
}
loginURL := api.LoginURL(registryName)
// An acrClient with authentication is generated, if the authentication cannot be resolved an error is returned.
acrClient, err := api.GetAcrCLIClientWithAuth(loginURL, annotateParams.username, annotateParams.password, annotateParams.configs)
if err != nil {
return err
}
orasClient, err := api.GetORASClientWithAuth(annotateParams.username, annotateParams.password, annotateParams.configs)
if err != nil {
return err
}
// A map is used to collect the regex tags for every repository.
tagFilters, err := common.CollectTagFilters(ctx, annotateParams.filters, acrClient.AutorestClient, annotateParams.filterTimeout, defaultRepoPageSize)
if err != nil {
return err
}
// A clarification message for --dry-run.
if annotateParams.dryRun {
fmt.Println("DRY RUN: The following output shows what WOULD be annotated if the annotate command was executed. Nothing is annotated.")
}
// In order to print a summary of the annotated tags/manifests, the counters get updated every time a repo is annotated.
annotatedTagsCount := 0
annotatedManifestsCount := 0
poolSize := annotateParams.concurrency
if poolSize <= 0 {
poolSize = defaultPoolSize
fmt.Printf("Specified concurrency value invalid. Set to default value: %d \n", defaultPoolSize)
} else if poolSize > maxPoolSize {
poolSize = maxPoolSize
fmt.Printf("Specified concurrency value too large. Set to maximum value: %d \n", maxPoolSize)
}
for repoName, tagRegex := range tagFilters {
singleAnnotatedTagsCount, err := annotateTags(ctx, acrClient, orasClient, poolSize, loginURL, repoName, annotateParams.artifactType, annotateParams.annotations, tagRegex, annotateParams.filterTimeout, annotateParams.dryRun)
if err != nil {
return fmt.Errorf("failed to annotate tags: %w", err)
}
singleAnnotatedManifestsCount := 0
// If the untagged flag is set, then manifests with no tags are also annotated..
if annotateParams.untagged {
singleAnnotatedManifestsCount, err = annotateUntaggedManifests(ctx, acrClient, orasClient, poolSize, loginURL, repoName, annotateParams.artifactType, annotateParams.annotations, annotateParams.dryRun)
if err != nil {
return fmt.Errorf("failed to annotate manifests: %w", err)
}
}
// After every repository is annotated, the counters are updated
annotatedTagsCount += singleAnnotatedTagsCount
annotatedManifestsCount += singleAnnotatedManifestsCount
}
// After all repos have been annotated, the summary is printed
if annotateParams.dryRun {
fmt.Printf("\nNumber of tags to be annotated: %d", annotatedTagsCount)
fmt.Printf("\nNumber of manifests to be annotated: %d\n", annotatedManifestsCount)
} else {
fmt.Printf("\nNumber of annotated tags: %d", annotatedTagsCount)
fmt.Printf("\nNumber of annotated manifests: %d\n", annotatedManifestsCount)
}
return nil
},
}
cmd.Flags().StringArrayVarP(&annotateParams.filters, "filter", "f", nil, `Specify the repository and a regular expression filter for the tag name. If a tag matches the filter, it will be annotated. If multiple tags refer to the same manifest and a tag matches the filter, the manifest will be annotated.
Note: If backtracking is used in the regexp it's possible for the expression to run into an infinite loop. The default timeout is set to 1 minute for evaluation of any filter expression. Use the '--filter-timeout-seconds' option to set a different value`)
cmd.Flags().Int64Var(&annotateParams.filterTimeout, "filter-timeout-seconds", defaultRegexpMatchTimeoutSeconds, "This limits the evaluation of the regex filter, and will return a timeout error if this duration is exceeded during a single evaluation. If written incorrectly a regexp filter with backtracking can result in an infinite loop")
cmd.Flags().StringVar(&annotateParams.artifactType, "artifact-type", "", "The configurable artifact type for an organization")
cmd.Flags().StringSliceVarP(&annotateParams.annotations, "annotations", "a", []string{}, "The configurable annotation key value that can be specified one or more times")
cmd.Flags().BoolVar(&annotateParams.untagged, "untagged", false, "If the untagged flag is set, all the manifests that do not have any tags associated to them will also be annotated, except if they belong to a manifest list that contains at least one tag")
cmd.Flags().BoolVar(&annotateParams.dryRun, "dry-run", false, "If the dry-run flag is set, no manifest or tag will be annotated. The output would be the same as if they were annotated")
cmd.Flags().IntVar(&annotateParams.concurrency, "concurrency", defaultPoolSize, annotatedConcurrencyDescription)
cmd.Flags().BoolP("help", "h", false, "Print usage")
cmd.MarkFlagRequired("filter")
cmd.MarkFlagRequired("artifact-type")
cmd.MarkFlagRequired("annotations")
return cmd
}