From a81dd4d990dd1754b6c34d0fefd22dcfff70bff6 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Fri, 15 Mar 2024 16:13:21 +0000 Subject: [PATCH 1/3] bugfix: don't assume a fixed number of segments in blob resource IDs --- storage/2020-08-04/blob/blobs/resource_id.go | 4 ++-- storage/2020-08-04/file/shares/resource_id.go | 2 +- storage/2023-11-03/blob/blobs/resource_id.go | 4 ++-- storage/2023-11-03/file/shares/resource_id.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/storage/2020-08-04/blob/blobs/resource_id.go b/storage/2020-08-04/blob/blobs/resource_id.go index a31673f..1a9352a 100644 --- a/storage/2020-08-04/blob/blobs/resource_id.go +++ b/storage/2020-08-04/blob/blobs/resource_id.go @@ -68,8 +68,8 @@ func ParseBlobID(input, domainSuffix string) (*BlobId, error) { path := strings.TrimPrefix(uri.Path, "/") segments := strings.Split(path, "/") - if len(segments) != 2 { - return nil, fmt.Errorf("expected the path to contain 2 segments but got %d", len(segments)) + if len(segments) < 2 { + return nil, fmt.Errorf("expected the path to contain at least 2 segments but got %d", len(segments)) } containerName := segments[0] diff --git a/storage/2020-08-04/file/shares/resource_id.go b/storage/2020-08-04/file/shares/resource_id.go index 73b93bd..b17f510 100644 --- a/storage/2020-08-04/file/shares/resource_id.go +++ b/storage/2020-08-04/file/shares/resource_id.go @@ -70,7 +70,7 @@ func ParseShareID(input, domainSuffix string) (*ShareId, error) { path := strings.TrimPrefix(uri.Path, "/") segments := strings.Split(path, "/") if len(segments) == 0 { - return nil, fmt.Errorf("Expected the path to contain segments but got none") + return nil, fmt.Errorf("expected the path to contain segments but got none") } shareName := strings.TrimPrefix(uri.Path, "/") diff --git a/storage/2023-11-03/blob/blobs/resource_id.go b/storage/2023-11-03/blob/blobs/resource_id.go index 95b78f5..5e5a9fa 100644 --- a/storage/2023-11-03/blob/blobs/resource_id.go +++ b/storage/2023-11-03/blob/blobs/resource_id.go @@ -68,8 +68,8 @@ func ParseBlobID(input, domainSuffix string) (*BlobId, error) { path := strings.TrimPrefix(uri.Path, "/") segments := strings.Split(path, "/") - if len(segments) != 2 { - return nil, fmt.Errorf("expected the path to contain 2 segments but got %d", len(segments)) + if len(segments) < 2 { + return nil, fmt.Errorf("expected the path to contain at least 2 segments but got %d", len(segments)) } containerName := segments[0] diff --git a/storage/2023-11-03/file/shares/resource_id.go b/storage/2023-11-03/file/shares/resource_id.go index c46092b..d323659 100644 --- a/storage/2023-11-03/file/shares/resource_id.go +++ b/storage/2023-11-03/file/shares/resource_id.go @@ -70,7 +70,7 @@ func ParseShareID(input, domainSuffix string) (*ShareId, error) { path := strings.TrimPrefix(uri.Path, "/") segments := strings.Split(path, "/") if len(segments) == 0 { - return nil, fmt.Errorf("Expected the path to contain segments but got none") + return nil, fmt.Errorf("expected the path to contain segments but got none") } shareName := strings.TrimPrefix(uri.Path, "/") From 3d7f148af9ceb57428b0375fd22a5c2dbf870582 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Mon, 18 Mar 2024 21:37:14 +0000 Subject: [PATCH 2/3] additional tests for nested blob resource IDs --- .../2020-08-04/blob/blobs/resource_id_test.go | 49 +++++++++++++++++++ .../2023-11-03/blob/blobs/resource_id_test.go | 49 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/storage/2020-08-04/blob/blobs/resource_id_test.go b/storage/2020-08-04/blob/blobs/resource_id_test.go index ae3ab02..eb453b8 100644 --- a/storage/2020-08-04/blob/blobs/resource_id_test.go +++ b/storage/2020-08-04/blob/blobs/resource_id_test.go @@ -39,6 +39,38 @@ func TestParseBlobIDStandard(t *testing.T) { } } +func TestParseNestedBlobIDStandard(t *testing.T) { + input := "https://example1.blob.core.windows.net/container1/more/deeply/nested/blob1.vhd" + expected := BlobId{ + AccountId: accounts.AccountId{ + AccountName: "example1", + SubDomainType: accounts.BlobSubDomainType, + DomainSuffix: "core.windows.net", + }, + ContainerName: "container1", + BlobName: "more/deeply/nested/blob1.vhd", + } + actual, err := ParseBlobID(input, "core.windows.net") + if err != nil { + t.Fatalf(err.Error()) + } + if actual.AccountId.AccountName != expected.AccountId.AccountName { + t.Fatalf("expected AccountName to be %q but got %q", expected.AccountId.AccountName, actual.AccountId.AccountName) + } + if actual.AccountId.SubDomainType != expected.AccountId.SubDomainType { + t.Fatalf("expected SubDomainType to be %q but got %q", expected.AccountId.SubDomainType, actual.AccountId.SubDomainType) + } + if actual.AccountId.DomainSuffix != expected.AccountId.DomainSuffix { + t.Fatalf("expected DomainSuffix to be %q but got %q", expected.AccountId.DomainSuffix, actual.AccountId.DomainSuffix) + } + if actual.ContainerName != expected.ContainerName { + t.Fatalf("expected ContainerName to be %q but got %q", expected.ContainerName, actual.ContainerName) + } + if actual.BlobName != expected.BlobName { + t.Fatalf("expected BlobName to be %q but got %q", expected.BlobName, actual.BlobName) + } +} + func TestParseBlobIDInADNSZone(t *testing.T) { input := "https://example1.zone1.blob.storage.azure.net/container1/blob1.vhd" expected := BlobId{ @@ -132,6 +164,23 @@ func TestFormatBlobIDStandard(t *testing.T) { } } +func TestFormatNestedBlobIDStandard(t *testing.T) { + actual := BlobId{ + AccountId: accounts.AccountId{ + AccountName: "example1", + SubDomainType: accounts.BlobSubDomainType, + DomainSuffix: "core.windows.net", + IsEdgeZone: false, + }, + ContainerName: "container1", + BlobName: "more/deeply/nested/somefile.vhd", + }.ID() + expected := "https://example1.blob.core.windows.net/container1/more/deeply/nested/somefile.vhd" + if actual != expected { + t.Fatalf("expected %q but got %q", expected, actual) + } +} + func TestFormatBlobIDInDNSZone(t *testing.T) { actual := BlobId{ AccountId: accounts.AccountId{ diff --git a/storage/2023-11-03/blob/blobs/resource_id_test.go b/storage/2023-11-03/blob/blobs/resource_id_test.go index 6e83de3..fe60fd9 100644 --- a/storage/2023-11-03/blob/blobs/resource_id_test.go +++ b/storage/2023-11-03/blob/blobs/resource_id_test.go @@ -39,6 +39,38 @@ func TestParseBlobIDStandard(t *testing.T) { } } +func TestParseNestedBlobIDStandard(t *testing.T) { + input := "https://example1.blob.core.windows.net/container1/more/deeply/nested/blob1.vhd" + expected := BlobId{ + AccountId: accounts.AccountId{ + AccountName: "example1", + SubDomainType: accounts.BlobSubDomainType, + DomainSuffix: "core.windows.net", + }, + ContainerName: "container1", + BlobName: "more/deeply/nested/blob1.vhd", + } + actual, err := ParseBlobID(input, "core.windows.net") + if err != nil { + t.Fatalf(err.Error()) + } + if actual.AccountId.AccountName != expected.AccountId.AccountName { + t.Fatalf("expected AccountName to be %q but got %q", expected.AccountId.AccountName, actual.AccountId.AccountName) + } + if actual.AccountId.SubDomainType != expected.AccountId.SubDomainType { + t.Fatalf("expected SubDomainType to be %q but got %q", expected.AccountId.SubDomainType, actual.AccountId.SubDomainType) + } + if actual.AccountId.DomainSuffix != expected.AccountId.DomainSuffix { + t.Fatalf("expected DomainSuffix to be %q but got %q", expected.AccountId.DomainSuffix, actual.AccountId.DomainSuffix) + } + if actual.ContainerName != expected.ContainerName { + t.Fatalf("expected ContainerName to be %q but got %q", expected.ContainerName, actual.ContainerName) + } + if actual.BlobName != expected.BlobName { + t.Fatalf("expected BlobName to be %q but got %q", expected.BlobName, actual.BlobName) + } +} + func TestParseBlobIDInADNSZone(t *testing.T) { input := "https://example1.zone1.blob.storage.azure.net/container1/blob1.vhd" expected := BlobId{ @@ -132,6 +164,23 @@ func TestFormatBlobIDStandard(t *testing.T) { } } +func TestFormatNestedBlobIDStandard(t *testing.T) { + actual := BlobId{ + AccountId: accounts.AccountId{ + AccountName: "example1", + SubDomainType: accounts.BlobSubDomainType, + DomainSuffix: "core.windows.net", + IsEdgeZone: false, + }, + ContainerName: "container1", + BlobName: "more/deeply/nested/somefile.vhd", + }.ID() + expected := "https://example1.blob.core.windows.net/container1/more/deeply/nested/somefile.vhd" + if actual != expected { + t.Fatalf("expected %q but got %q", expected, actual) + } +} + func TestFormatBlobIDInDNSZone(t *testing.T) { actual := BlobId{ AccountId: accounts.AccountId{ From 25a1a6abe0685dce9f641de523f0b641558fe229 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Mon, 18 Mar 2024 21:45:40 +0000 Subject: [PATCH 3/3] additional tests for parsing invalid nested blob resource IDs --- storage/2020-08-04/blob/blobs/resource_id_test.go | 15 +++++++++++++++ storage/2023-11-03/blob/blobs/resource_id_test.go | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/storage/2020-08-04/blob/blobs/resource_id_test.go b/storage/2020-08-04/blob/blobs/resource_id_test.go index eb453b8..c156b55 100644 --- a/storage/2020-08-04/blob/blobs/resource_id_test.go +++ b/storage/2020-08-04/blob/blobs/resource_id_test.go @@ -181,6 +181,21 @@ func TestFormatNestedBlobIDStandard(t *testing.T) { } } +func TestParseInvalidBlobIDStandard(t *testing.T) { + input := "https://example1.blob.core.windows.net/blobby.vhd" + actual, err := ParseBlobID(input, "core.windows.net") + if err == nil { + if actual != nil { + t.Fatalf("expected an error but got: %#v", *actual) + } else { + t.Fatalf("expected an error but got no error and a nil result") + } + } + if err.Error() != "expected the path to contain at least 2 segments but got 1" { + t.Fatalf("unexpected error received: %+v", err) + } +} + func TestFormatBlobIDInDNSZone(t *testing.T) { actual := BlobId{ AccountId: accounts.AccountId{ diff --git a/storage/2023-11-03/blob/blobs/resource_id_test.go b/storage/2023-11-03/blob/blobs/resource_id_test.go index fe60fd9..d8fc21e 100644 --- a/storage/2023-11-03/blob/blobs/resource_id_test.go +++ b/storage/2023-11-03/blob/blobs/resource_id_test.go @@ -71,6 +71,21 @@ func TestParseNestedBlobIDStandard(t *testing.T) { } } +func TestParseInvalidBlobIDStandard(t *testing.T) { + input := "https://example1.blob.core.windows.net/blobby.vhd" + actual, err := ParseBlobID(input, "core.windows.net") + if err == nil { + if actual != nil { + t.Fatalf("expected an error but got: %#v", *actual) + } else { + t.Fatalf("expected an error but got no error and a nil result") + } + } + if err.Error() != "expected the path to contain at least 2 segments but got 1" { + t.Fatalf("unexpected error received: %+v", err) + } +} + func TestParseBlobIDInADNSZone(t *testing.T) { input := "https://example1.zone1.blob.storage.azure.net/container1/blob1.vhd" expected := BlobId{