private void SynchronizedLoadAllHistory(Guid profileId) { IAwsClient client; AwsProfile profile; if (!TryInitialize(profileId, out client, out profile)) { return; } if (string.IsNullOrEmpty(profile.DetailedBillingS3Bucket)) { // detailed billing not configured for this profile return; } if (profile.IsBillingHistoryLoading) { return; } // Prevent other processes from trying to load at the same time. // This still has a race condition that would be eliminated using optimistic concurrency. profile.IsBillingHistoryLoading = true; _awsProfileRepository.Update(profile); // http://s3.amazonaws.com/509438855493-aws-billing-detailed-line-items-with-resources-and-tags-2014-08.csv.zip var pattern = new Regex(@"\A\d+-aws-billing-detailed-line-items-with-resources-and-tags-(\d+\-\d+).csv.zip\z"); var rootPath = new S3PathParts(profile.DetailedBillingS3Bucket, ""); List<string> availablePeriods = client.StorageService .ListFiles(rootPath.ToString()) .Select(path => _pathParser.Parse(path)) .Select(parsedPath => pattern.Match(parsedPath.Key)) .Where(match => match.Success) .Select(match => match.Groups[1].Captures[0].Value) .OrderBy(period => period, StringComparer.InvariantCulture) .ToList(); // Forget that we have pulled CSVs before... profile.BillingMetadata.Clear(); // ... or loaded them into the ledger. _billingManager.WipeAllData(); DateTime utcNow = _clock.UtcNow; foreach (string period in availablePeriods) { RefreshDataForPeriod(profile, period, client, utcNow); } profile.IsBillingHistoryLoaded = true; profile.IsBillingHistoryLoading = false; _awsProfileRepository.Update(profile); }
public void ToString_S3Url() { var parts = new S3PathParts("mybucket", "mykey"); parts.ToString().Should().Be("s3://mybucket/mykey"); }