cmd/hub/azure/blobs.go (110 lines of code) (raw):

// Copyright (c) 2022 EPAM Systems, Inc. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. package azure import ( "errors" "fmt" "io" "net/url" "os" "strings" "time" "github.com/Azure/azure-sdk-for-go/storage" "github.com/epam/hubctl/cmd/hub/util" ) var ( blobClients = make(map[string]*storage.BlobStorageClient) storageTimeoutSec = uint(10) storageTimeout = time.Duration((10 + 1) * time.Second) ) func storageClient(account string) (*storage.BlobStorageClient, error) { if client, exist := blobClients[account]; exist { return client, nil } _, env, err := settings() if err != nil { return nil, err } key, err := storageKey(account) if err != nil { return nil, err } storageClient, _ := storage.NewClient(account, key, env.StorageEndpointSuffix, storage.DefaultAPIVersion, true) storageClient.HTTPClient = util.RobustHttpClient(storageTimeout, false) blobClient := storageClient.GetBlobService() blobClients[account] = &blobClient return &blobClient, nil } func splitPath(path string) (string, string, string, error) { location, err := url.Parse(path) if err != nil { return "", "", "", err } parts := strings.SplitN(location.Path, "/", 3) if len(parts) != 3 { return "", "", "", errors.New("Bad path format") } return location.Host, parts[1], parts[2], nil } func StatStorageBlob(path string) (int64, time.Time, error) { account, container, name, err := splitPath(path) if err != nil { return 0, time.Time{}, err } blobClient, err := storageClient(account) if err != nil { return 0, time.Time{}, err } containerRef := blobClient.GetContainerReference(container) blobRef := containerRef.GetBlobReference(name) err = blobRef.GetProperties(nil) if err != nil { if IsNotFound(err) { return 0, time.Time{}, os.ErrNotExist } return 0, time.Time{}, err } props := blobRef.Properties return props.ContentLength, time.Time(props.LastModified), nil } func ReadStorageBlob(path string) ([]byte, error) { account, container, name, err := splitPath(path) if err != nil { return nil, err } blobClient, err := storageClient(account) if err != nil { return nil, err } containerRef := blobClient.GetContainerReference(container) blobRef := containerRef.GetBlobReference(name) reader, err := blobRef.Get(&storage.GetBlobOptions{Timeout: storageTimeoutSec}) if err != nil { return nil, err } defer reader.Close() data, err := io.ReadAll(reader) if err != nil { return nil, fmt.Errorf("Failed to read Azure storage blob `%s`: %v", path, err) } return data, nil } func WriteStorageBlob(path string, body []byte) error { account, container, name, err := splitPath(path) if err != nil { return err } blobClient, err := storageClient(account) if err != nil { return err } containerRef := blobClient.GetContainerReference(container) blobRef := containerRef.GetBlobReference(name) err = blobRef.PutAppendBlob(&storage.PutBlobOptions{Timeout: storageTimeoutSec}) if err != nil { return err } err = blobRef.AppendBlock(body, &storage.AppendBlockOptions{Timeout: storageTimeoutSec}) if err != nil { return fmt.Errorf("Failed to write Azure storage blob `%s`: %v", path, err) } return nil }