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;
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        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);
Beispiel #10
0
 public static EncryptedBlob Convert(byte[] input, Attribute config)
 => EncryptedBlob.FromByteArray(BlobPath.ParseAndValidate(((EncryptedBlobAttribute)config).BlobPath), input);
Beispiel #11
0
        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);
            }
        }
Beispiel #12
0
 public Task AddPathKeyPair(BlobPath path, string key)
 => AddPathKeyPair(path.ToString(), key);
Beispiel #13
0
 public Task <string> GetKeyByPath(BlobPath path)
 => GetKeyByPath(path.ToString());
Beispiel #14
0
 public BlobValueBindingContext(BlobPath path, ValueBindingContext context)
     : base(context.FunctionContext, context.CancellationToken)
 {
     Path = path;
 }
Beispiel #15
0
 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));
        }
Beispiel #17
0
 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;
 }
Beispiel #20
0
        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);
        }
Beispiel #21
0
 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 ']'.");
 }