Skip to content

Conversation

@KastenMike
Copy link
Contributor

Adds support for Azure PIT

@KastenMike KastenMike changed the title Azure pit support feat(repository): Add Azure PIT support Oct 26, 2023
@codecov
Copy link

codecov bot commented Nov 1, 2023

Codecov Report

Attention: 11 lines in your changes are missing coverage. Please review.

Comparison is base (174f614) 75.80% compared to head (7a2fc25) 75.82%.
Report is 21 commits behind head on master.

Files Patch % Lines
cli/storage_azure.go 26.66% 10 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3407      +/-   ##
==========================================
+ Coverage   75.80%   75.82%   +0.01%     
==========================================
  Files         465      465              
  Lines       37165    37180      +15     
==========================================
+ Hits        28174    28192      +18     
- Misses       7059     7061       +2     
+ Partials     1932     1927       -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@julio-lopez
Copy link
Collaborator

@KastenMike see initial comments


func (az *azStorage) getBlobName(it *azblobmodels.BlobItem) string {
n := *it.Name
return n[len(az.Prefix):]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use strings.TrimPrefix here, it is more robust.

Also additional defensive programming should be applied here to prevent a panic due to a nil dereference. Given the Azure SDK API, where all the structs have pointers, then it makes sense to add helpers that either (a) validate and return an error; or (b) return sane default values.

Suggested change
return n[len(az.Prefix):]
return strings.TrimPrefix(toString(*it.Name), az.prefix)

toString would be defined as:

func toString(s *string) string {
	return stringDefault(s, "")
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code has been in kopia for a long time so I guess azure returns an error rather than null values for the common metadata. I just extracted it to a method

return n[len(az.Prefix):]
}

func (az *azStorage) getBlobMeta(it *azblobmodels.BlobItem) blob.Metadata {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check for it != nil

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same as above~ the code has been in since February without issue so I guess there is always a blob item if the loop is entered

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. The hardening can be done separately.

func (az *azStorage) getBlobMeta(it *azblobmodels.BlobItem) blob.Metadata {
bm := blob.Metadata{
BlobID: blob.ID(az.getBlobName(it)),
Length: *it.Properties.ContentLength,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check to ensure that:

  • it.Properties != nil
  • it.Properties.ContentLength != nil

before dereferencing.

}

// see if we have 'Kopiamtime' metadata, if so - trust it.
if t, ok := timestampmeta.FromValue(stringDefault(it.Metadata["kopiamtime"], "")); ok {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: after adding toString, then it can be used here.

Suggested change
if t, ok := timestampmeta.FromValue(stringDefault(it.Metadata["kopiamtime"], "")); ok {
if t, ok := timestampmeta.FromValue(toString(it.Metadata["kopiamtime"])); ok {

if t, ok := timestampmeta.FromValue(stringDefault(it.Metadata["kopiamtime"], "")); ok {
bm.Timestamp = t
} else {
bm.Timestamp = *it.Properties.LastModified
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto: validate the chain to ensure there are no nil components

Copy link
Collaborator

@julio-lopez julio-lopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG overall.

I am not completely sure about the handling of the deletion marker.
And a few inline comments.

return n[len(az.Prefix):]
}

func (az *azStorage) getBlobMeta(it *azblobmodels.BlobItem) blob.Metadata {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. The hardening can be done separately.

@julio-lopez
Copy link
Collaborator

Provider tests are failing for Azure Blob
https://github.com/kopia/kopia/actions/runs/6751751502/job/18356268523?pr=3407

"github.com/kopia/kopia/repo/format"
)

func TestGetBlobVersions(t *testing.T) {
Copy link
Collaborator

@julio-lopez julio-lopez Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KastenMike This test and the one below are failing in the "test/providers" job. The likely cause is that the buckets used in the test do not have the required setup, that is version-level immutability enabled.

That's the only thing left to merge this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you re-run the tests? I cannot see run history & you didn't link a new run. Now it doesn't check for version-level immutability

Copy link
Contributor Author

@KastenMike KastenMike Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I see it in Actions. Someone should enable versioning on the related storage account for it to work https://learn.microsoft.com/en-us/azure/storage/blobs/versioning-enable?tabs=portal

Copy link
Contributor Author

@KastenMike KastenMike Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the process whoever sets it could enable version-level immutability on the container since it seems the SDK doesn't support it and it's required for #3412 tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jkowalski is it something you'd be able to enable?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mike: this requires a little more than that.

These 2 tests need to run in a different setup. That means:

  • setting up a separate storage account with version-level immutability enabled (as you mentioned).
  • create a new bucket with version-level immutability, or have the test create it with the desired settings.
  • these tests need to use a separate 'credentials setting' from the environment. The actual credentials may be the same, but the storage account and bucket would be different.
  • the GH environment needs to be updated with these new cred information.

Copy link
Contributor Author

@KastenMike KastenMike Nov 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it require a separate storage account? you could simply have the same one running new + existing tests but with 2 new settings changed. When turning on versioning it gives the option to use Azure's BLM which can be set to delete versions older than 1 day

Copy link
Collaborator

@julio-lopez julio-lopez Nov 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KastenMike For what I understand, the storage account currently used in the tests does not have versioning, nor immutability enabled. I thought that version immutability needed to be enabled at the storage account level. This is what I recall but I could be mistaken. I'll double check.

Also, we don't want to enable versioning for the default tests, since the default / common use case does not require nor use versioning by default.

If no separate storage account is needed, then it is a matter of simply creating a separate container with the appropriate settings.

PTAL at https://github.com/kopia/kopia/compare/azure-immutability-setup

This contains the setup code for the storage account and the container. PLMK if that makes sense, if there's anything missing or that needs to be changed.

Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting ImmutableStorageWithVersioning to true via CLI is automatically making versioning be enabled too? In the UI they make you do 2 separate actions. A policy isn’t needed on the container~ only versioning + ImmutableStorageWithVersioning
If the intention would be to run it repeatedly like the createContainer currently then it needs checks for "already exists" errors also on the SA & container

Copy link
Collaborator

@julio-lopez julio-lopez Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behavior observed using the console: attempting to enable "version immutability" in the container requires enabling "versioning" in the storage account. It wasn't clear at that moment what the implication was for existing buckets, so we created a separate storage account and bucket.

See comment below

@julio-lopez
Copy link
Collaborator

@redgoat650 Do you have any comments?

@julio-lopez
Copy link
Collaborator

julio-lopez commented Nov 28, 2023

@KastenMike FYI #3471 was missing in the setup. All good now.

Copy link
Collaborator

@julio-lopez julio-lopez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KastenMike 🥇Thanks for doing this.

LGTM ✅

@julio-lopez julio-lopez merged commit d4a380f into kopia:master Nov 28, 2023
@KastenMike KastenMike deleted the Azure-PIT-support branch September 26, 2024 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants