testSuite/cmd/list.go (100 lines of code) (raw):

package cmd import ( "context" "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "net/url" "os" "strings" "github.com/Azure/azure-storage-azcopy/v10/ste" "github.com/spf13/cobra" ) // initializes the clean command, its aliases and description. func init() { resourceUrl := "" numberOfResource := int64(0) cleanCmd := &cobra.Command{ Use: "list", Aliases: []string{"list"}, Short: "lists list everything inside the container / virtual directory", Args: func(cmd *cobra.Command, args []string) error { if len(args) > 1 { return fmt.Errorf("invalid arguments for clean command") } resourceUrl = args[0] return nil }, Run: func(cmd *cobra.Command, args []string) { listContainer(resourceUrl, numberOfResource) }, } rootCmd.AddCommand(cleanCmd) cleanCmd.PersistentFlags().Int64Var(&numberOfResource, "resource-num", 0, "number of resource inside the container") } func getContainerURLFromString(url url.URL) string { containerName := strings.SplitAfterN(url.Path[1:], "/", 2)[0] url.Path = "/" + containerName return url.String() } // checks if a given url points to a container, as opposed to a blob or prefix match func urlIsContainerOrShare(url *url.URL) bool { // if the path contains more than one "/", then it means it points to a blob, and not a container numOfSlashes := strings.Count(url.Path[1:], "/") if numOfSlashes == 0 { return true } else if numOfSlashes == 1 && url.Path[len(url.Path)-1:] == "/" { // this checks if container_name/ was given return true } return false } func getBlobNameFromURL(path string) string { // return everything after the second / return strings.SplitAfterN(path[1:], "/", 2)[1] } func listContainer(resourceUrl string, numberOfResources int64) { // attempt to parse the source url sourceUrl, err := url.Parse(resourceUrl) if err != nil { fmt.Println("cannot parse source URL") os.Exit(1) } // get the container url to be used for listing literalContainerUrl := getContainerURLFromString(*sourceUrl) cc, err := container.NewClientWithNoCredential(literalContainerUrl, &container.ClientOptions{ClientOptions: azcore.ClientOptions{ Retry: policy.RetryOptions{ MaxRetries: ste.UploadMaxTries, TryTimeout: ste.UploadTryTimeout, RetryDelay: ste.UploadRetryDelay, MaxRetryDelay: ste.UploadMaxRetryDelay, }, }}) if err != nil { fmt.Printf("cannot create container client. Failed with error %s\n", err.Error()) os.Exit(1) } // get the search prefix to query the service searchPrefix := "" // if the source is container url, then searchPrefix is empty if !urlIsContainerOrShare(sourceUrl) { searchPrefix = getBlobNameFromURL(sourceUrl.Path) } if len(searchPrefix) > 0 { // if the user did not specify / at the end of the virtual directory, add it before doing the prefix search if strings.LastIndex(searchPrefix, "/") != len(searchPrefix)-1 { searchPrefix += "/" } } numberOfBlobs := int64(0) // perform a list blob // look for all blobs that start with the prefix pager := cc.NewListBlobsFlatPager(&container.ListBlobsFlatOptions{Prefix: &searchPrefix}) for pager.More() { listBlob, err := pager.NextPage(context.TODO()) if err != nil { fmt.Printf("cannot list blobs for download. Failed with error %s\n", err.Error()) os.Exit(1) } // Process the blobs returned in this result segment (if the segment is empty, the loop body won't execute) for _, blobInfo := range listBlob.Segment.BlobItems { blobName := *blobInfo.Name if len(searchPrefix) > 0 { // strip away search prefix from the blob name. blobName = strings.Replace(blobName, searchPrefix, "", 1) //nolint:ineffassign,staticcheck } numberOfBlobs++ } } if numberOfBlobs != numberOfResources { fmt.Printf("expected number of blobs / file %d inside the resource does not match the actual %d\n", numberOfResources, numberOfBlobs) os.Exit(1) } }