internal static bool TryConvert(object value, IStorageBlobClient client, out IStorageBlobContainer container, out BlobPath path) { container = null; path = null; string fullPath = value as string; if (fullPath != null) { path = BlobPath.ParseAndValidate(fullPath, isContainerBinding: true); container = client.GetContainerReference(path.ContainerName); return true; } return false; }
private async Task <ICloudBlob> GetBlobAsync( BlobAttribute blobAttribute, CancellationToken cancellationToken, Type requestedType = null) { var client = await GetClientAsync(blobAttribute, cancellationToken); BlobPath boundPath = BlobPath.ParseAndValidate(blobAttribute.BlobPath); var container = client.GetContainerReference(boundPath.ContainerName); // Call ExistsAsync before attempting to create. This reduces the number of // 40x calls that App Insights may be tracking automatically if (blobAttribute.Access != FileAccess.Read && !await container.ExistsAsync()) { await container.CreateIfNotExistsAsync(cancellationToken); } var blob = await container.GetBlobReferenceForArgumentTypeAsync( boundPath.BlobName, requestedType, cancellationToken); return(blob); }
private static IDictionary <string, string> Match(string a, string b) { var pathA = BlobPathSource.Create(a); BlobPath pathB = null; BlobPath.TryParse(b, false, out pathB); IReadOnlyDictionary <string, object> bindingData = pathA.CreateBindingData(pathB); if (bindingData == null) { return(null); } IDictionary <string, string> matches = new Dictionary <string, string>(); foreach (KeyValuePair <string, object> item in bindingData) { matches.Add(item.Key, item.Value.ToString()); } return(matches); }
/// <summary> /// Attempts to retrieve a blob path out of log entry's RequestedObjectKey. /// </summary> /// <returns> /// A valid instance of <see cref="BlobPath"/>, or null if log entry is not associated with a blob. /// </returns> public BlobPath ToBlobPath() { if (!ServiceType.HasValue || ServiceType != StorageServiceType.Blob) { return(null); } string path; Uri keyAsUri = new Uri(RequestedObjectKey, UriKind.RelativeOrAbsolute); if (keyAsUri.IsAbsoluteUri) { // assuming key is "https://storagesample.blob.core.windows.net/sample-container/sample-blob.txt" path = keyAsUri.Segments.Length > 1 ? keyAsUri.LocalPath.Substring(1) : String.Empty; } else { // assuming key is "/account/container/blob" int startPos = RequestedObjectKey.Length > 1 ? RequestedObjectKey.IndexOf('/', 1) : -1; path = startPos != -1 ? RequestedObjectKey.Substring(startPos + 1) : String.Empty; } if (String.IsNullOrEmpty(path)) { return(null); } BlobPath blobPath; if (!BlobPath.TryParse(path, false, out blobPath)) { return(null); } return(blobPath); }
public void GetPathsForValidBlobWrites_Returns_ValidBlobWritesOnly() { StorageAnalyticsLogEntry[] entries = new[] { // This is a valid write entry with a valid path new StorageAnalyticsLogEntry { ServiceType = StorageServiceType.Blob, OperationType = StorageServiceOperationType.PutBlob, RequestedObjectKey = @"/storagesample/sample-container/""0x8D199A96CB71468""/sample-blob.txt" }, // This is an invalid path and will be filtered out new StorageAnalyticsLogEntry { ServiceType = StorageServiceType.Blob, OperationType = StorageServiceOperationType.PutBlob, RequestedObjectKey = "/" }, // This does not constitute a write and will be filtered out new StorageAnalyticsLogEntry { ServiceType = StorageServiceType.Blob, OperationType = null, RequestedObjectKey = @"/storagesample/sample-container/""0x8D199A96CB71468""/sample-blob.txt" } }; IEnumerable <BlobPath> validPaths = BlobLogListener.GetPathsForValidBlobWrites(entries); BlobPath singlePath = validPaths.Single(); Assert.Equal("sample-container", singlePath.ContainerName); Assert.Equal(@"""0x8D199A96CB71468""/sample-blob.txt", singlePath.BlobName); }
public void ParseAndValidate_IfHierarchicalBlobName_ReturnsBlobPath() { BlobPath blobPath = BlobPath.ParseAndValidate(@"container/my/blob"); Assert.NotNull(blobPath); }
public void ParseAndValidate_IfBackslashInBlobName_ThrowsFormatException() { ExceptionAssert.ThrowsFormat(() => BlobPath.ParseAndValidate(@"container/my\name"), "The given blob name 'my\\name' contain illegal characters. A blob name cannot the following character(s): '\\'."); }
public void ParseAndValidate_IfInvalidContainerName_ThrowsFormatException() { ExceptionAssert.ThrowsFormat(() => BlobPath.ParseAndValidate(@"container-/blob"), "Invalid container name: container-"); }
private CloudBlobContainer GetContainer(BlobPath blobPath) => _blobClient.GetContainerReference(blobPath.ContainerName);
public static EncryptedBlob Convert(byte[] input, Attribute config) => EncryptedBlob.FromByteArray(BlobPath.ParseAndValidate(((EncryptedBlobAttribute)config).BlobPath), input);
public async Task <FunctionResult> ExecuteAsync(BlobTriggerExecutorContext context, CancellationToken cancellationToken) { BlobBaseClient value = context.Blob.BlobClient; BlobTriggerScanSource triggerSource = context.TriggerSource; string pollId = context.PollId; // Avoid unnecessary network calls for non-matches. First, check to see if the blob matches this trigger. IReadOnlyDictionary <string, object> bindingData = _input.CreateBindingData(value.ToBlobPath()); if (bindingData == null) { string pattern = new BlobPath(_input.ContainerNamePattern, _input.BlobNamePattern).ToString(); Logger.BlobDoesNotMatchPattern(_logger, _functionDescriptor.LogName, value.Name, pattern, pollId, triggerSource); // Blob is not a match for this trigger. return(new FunctionResult(true)); } // Next, check to see if the blob currently exists (and, if so, what the current ETag is). BlobProperties blobProperties = await value.FetchPropertiesOrNullIfNotExistAsync(cancellationToken).ConfigureAwait(false); string possibleETag = null; if (blobProperties != null) { possibleETag = blobProperties.ETag.ToString(); } if (possibleETag == null) { Logger.BlobHasNoETag(_logger, _functionDescriptor.LogName, value.Name, pollId, triggerSource); // If the blob doesn't exist and have an ETag, don't trigger on it. return(new FunctionResult(true)); } var receiptBlob = _receiptManager.CreateReference(_hostId, _functionDescriptor.Id, value.BlobContainerName, value.Name, possibleETag); // Check for the completed receipt. If it's already there, noop. BlobReceipt unleasedReceipt = await _receiptManager.TryReadAsync(receiptBlob, cancellationToken).ConfigureAwait(false); if (unleasedReceipt != null && unleasedReceipt.IsCompleted) { Logger.BlobAlreadyProcessed(_logger, _functionDescriptor.LogName, value.Name, possibleETag, pollId, triggerSource); return(new FunctionResult(true)); } else if (unleasedReceipt == null) { // Try to create (if not exists) an incomplete receipt. if (!await _receiptManager.TryCreateAsync(receiptBlob, cancellationToken).ConfigureAwait(false)) { // Someone else just created the receipt; wait to try to trigger until later. // Alternatively, we could just ignore the return result and see who wins the race to acquire the // lease. return(new FunctionResult(false)); } } string leaseId = await _receiptManager.TryAcquireLeaseAsync(receiptBlob, cancellationToken).ConfigureAwait(false); if (leaseId == null) { // If someone else owns the lease and just took over this receipt or deleted it; // wait to try to trigger until later. return(new FunctionResult(false)); } try { // Check again for the completed receipt. If it's already there, noop. BlobReceipt receipt = await _receiptManager.TryReadAsync(receiptBlob, cancellationToken).ConfigureAwait(false); Debug.Assert(receipt != null); // We have a (30 second) lease on the blob; it should never disappear on us. if (receipt.IsCompleted) { Logger.BlobAlreadyProcessed(_logger, _functionDescriptor.LogName, value.Name, possibleETag, pollId, triggerSource); await _receiptManager.ReleaseLeaseAsync(receiptBlob, leaseId, cancellationToken).ConfigureAwait(false); return(new FunctionResult(true)); } // We've successfully acquired a lease to enqueue the message for this blob trigger. Enqueue the message, // complete the receipt and release the lease. // Enqueue a message: function ID + blob path + ETag BlobTriggerMessage message = new BlobTriggerMessage { FunctionId = _functionDescriptor.Id, BlobType = blobProperties.BlobType, ContainerName = value.BlobContainerName, BlobName = value.Name, ETag = possibleETag }; var(queueName, messageId) = await _queueWriter.EnqueueAsync(message, cancellationToken).ConfigureAwait(false); Logger.BlobMessageEnqueued(_logger, _functionDescriptor.LogName, value.Name, messageId, queueName, pollId, triggerSource); // Complete the receipt await _receiptManager.MarkCompletedAsync(receiptBlob, leaseId, cancellationToken).ConfigureAwait(false); return(new FunctionResult(true)); } finally { await _receiptManager.ReleaseLeaseAsync(receiptBlob, leaseId, cancellationToken).ConfigureAwait(false); } }
public Task AddPathKeyPair(BlobPath path, string key) => AddPathKeyPair(path.ToString(), key);
public Task <string> GetKeyByPath(BlobPath path) => GetKeyByPath(path.ToString());
public BlobValueBindingContext(BlobPath path, ValueBindingContext context) : base(context.FunctionContext, context.CancellationToken) { Path = path; }
public static EncryptedBlob Convert(string input, Attribute config) => EncryptedBlob.FromString(BlobPath.ParseAndValidate(((EncryptedBlobAttribute)config).BlobPath), input);
public ActionResult SearchBlob(string path) { ViewBag.Path = path; if (String.IsNullOrEmpty(path)) { return(View()); } if (_account == null) { TempData["Message.Text"] = "Account not found"; TempData["Message.Level"] = "danger"; return(View()); } ICloudBlob blob = null; try { BlobPath parsed = BlobPath.Parse(path); LocalBlobDescriptor descriptor = new LocalBlobDescriptor { ContainerName = parsed.ContainerName, BlobName = parsed.BlobName }; IReadOnlyDictionary <string, CloudStorageAccount> accounts = AccountProvider.GetAccounts(); foreach (var account in accounts.Values) { blob = descriptor.GetBlockBlob(account); if (blob.Exists()) { break; } else { blob = null; } } } catch (FormatException e) { TempData["Message.Text"] = e.Message; TempData["Message.Level"] = "danger"; return(View()); } catch { blob = null; } if (blob == null) { TempData["Message.Text"] = "No invocation found for: " + path; TempData["Message.Level"] = "warning"; return(View()); } Guid?guid; try { guid = BlobCausalityReader.GetParentId(blob); } catch { guid = null; } if (!guid.HasValue) { TempData["Message.Text"] = "No invocation found for: " + path; TempData["Message.Level"] = "warning"; return(View()); } TempData["Message.Text"] = "Invocation found for: " + path; TempData["Message.Level"] = "info"; return(Redirect("~/#/functions/invocations/" + guid)); }
public static ICloudBlob GetBlobReferenceFromType(this CloudBlobContainer container, BlobPath blobPath, BlobType?blobType) => blobType switch {
public async Task <ICloudBlob> GetBlob(BlobPath blobPath, CancellationToken cancellationToken = default) { var container = await GetOrCreateContainer(blobPath, cancellationToken); return(await container.GetBlobReferenceFromServerAsync(blobPath.BlobName, null, new BlobRequestOptions { EncryptionPolicy = GetEncryptionPolicyForDownload() }, null, cancellationToken)); }
public BlobValueBindingContext(BlobPath path, ValueBindingContext context) : base(context.FunctionContext, context.CancellationToken) { Path = path; }
internal static bool TryConvert(object value, IStorageBlobClient client, out IStorageBlobContainer container, out BlobPath path) { container = null; path = null; string fullPath = value as string; if (fullPath != null) { path = BlobPath.ParseAndValidate(fullPath, isContainerBinding: true); container = client.GetContainerReference(path.ContainerName); return(true); } return(false); }
public void ParseAndValidate_IfCloseSquareBracketInBlobName_ThrowsFormatException() { ExceptionAssert.ThrowsFormat(() => BlobPath.ParseAndValidate(@"container/my]name"), "The given blob name 'my]name' contain illegal characters. A blob name cannot the following characters: '\\', '[' and ']'."); }