public RuleWrapper(AggregatorConfiguration configuration, ILogger logger, string ruleName, string functionDirectory) { this.configuration = configuration; this.logger = logger; this.ruleName = ruleName; this.functionDirectory = functionDirectory; }
static public AggregatorConfiguration Read(Microsoft.Extensions.Configuration.IConfiguration config) { var ac = new AggregatorConfiguration(); Enum.TryParse(config["Aggregator_VstsTokenType"], out VstsTokenType vtt); ac.VstsTokenType = vtt; ac.VstsToken = config["Aggregator_VstsToken"]; return(ac); }
static public AggregatorConfiguration Read(Microsoft.Extensions.Configuration.IConfiguration config) { var ac = new AggregatorConfiguration(); Enum.TryParse(config["Aggregator_VstsTokenType"], out DevOpsTokenType vtt); ac.DevOpsTokenType = vtt; ac.DevOpsToken = config["Aggregator_VstsToken"]; ac.SaveMode = Enum.TryParse(config["Aggregator_SaveMode"], out SaveMode sm) ? sm : SaveMode.Default; return(ac); }
public async Task <HttpResponseMessage> Run(HttpRequestMessage req) { log.Verbose($"Context: {context.InvocationId} {context.FunctionName} {context.FunctionDirectory} {context.FunctionAppDirectory}"); // TODO string aggregatorVersion = null; try { string rule = context.FunctionName; log.Info($"Welcome to {rule}"); } catch (Exception ex) { log.Warning($"Failed parsing headers: {ex.Message}"); } // Get request body string jsonContent = await req.Content.ReadAsStringAsync(); dynamic data = JsonConvert.DeserializeObject(jsonContent); string eventType = data.eventType; // sanity check if (!VstsEvents.IsValidEvent(eventType) || data.publisherId != VstsEvents.PublisherId) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Not a good VSTS post..." })); } var config = new ConfigurationBuilder() .SetBasePath(context.FunctionAppDirectory) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var configuration = AggregatorConfiguration.Read(config); var logger = new TraceWriterLogger(log); var wrapper = new RuleWrapper(configuration, logger, context.FunctionName, context.FunctionDirectory); string execResult = await wrapper.Execute(aggregatorVersion, data); log.Info($"Returning {execResult}"); var resp = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(execResult) }; return(resp); }
public static AggregatorConfiguration ExtendFromUrl(AggregatorConfiguration configuration, Uri requestUri) { var parameters = System.Web.HttpUtility.ParseQueryString(requestUri.Query); bool dryRun = bool.TryParse(parameters["dryRun"], out dryRun) && dryRun; configuration.DryRun = dryRun; if (Enum.TryParse(parameters["saveMode"], out SaveMode saveMode)) { configuration.SaveMode = saveMode; } return(configuration); }
public async Task <HttpResponseMessage> RunAsync(HttpRequestMessage req, CancellationToken cancellationToken) { _log.LogDebug($"Context: {_context.InvocationId} {_context.FunctionName} {_context.FunctionDirectory} {_context.FunctionAppDirectory}"); var aggregatorVersion = GetCustomAttribute <System.Reflection.AssemblyInformationalVersionAttribute>()?.InformationalVersion; try { var rule = _context.FunctionName; _log.LogInformation($"Aggregator v{aggregatorVersion} executing rule '{rule}'"); } catch (Exception ex) { _log.LogWarning($"Failed parsing request headers: {ex.Message}"); } cancellationToken.ThrowIfCancellationRequested(); // Get request body var jsonContent = await req.Content.ReadAsStringAsync(); if (string.IsNullOrWhiteSpace(jsonContent)) { _log.LogWarning($"Failed parsing request body: empty"); var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent("Request body is empty") }; return(resp); } dynamic data = JsonConvert.DeserializeObject(jsonContent); string eventType = data.eventType; // sanity check if (!DevOpsEvents.IsValidEvent(eventType) || data.publisherId != DevOpsEvents.PublisherId) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Not a good Azure DevOps post..." })); } if (data.resource.url == "http://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/wit/workItems/5") { var resp = req.CreateResponse(HttpStatusCode.OK, new { message = $"Hello from Aggregator v{aggregatorVersion} executing rule '{_context.FunctionName}'" }); resp.Headers.Add("X-Aggregator-Version", aggregatorVersion); resp.Headers.Add("X-Aggregator-Rule", _context.FunctionName); return(resp); } var config = new ConfigurationBuilder() .SetBasePath(_context.FunctionAppDirectory) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var configuration = AggregatorConfiguration.Read(config); configuration = InvokeOptions.ExtendFromUrl(configuration, req.RequestUri); var logger = new ForwarderLogger(_log); var wrapper = new RuleWrapper(configuration, logger, _context.FunctionName, _context.FunctionDirectory); try { string execResult = await wrapper.ExecuteAsync(data, cancellationToken); if (string.IsNullOrEmpty(execResult)) { var resp = new HttpResponseMessage(HttpStatusCode.OK); return(resp); } else { _log.LogInformation($"Returning '{execResult}' from '{_context.FunctionName}'"); var resp = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(execResult) }; return(resp); } } catch (Exception ex) { _log.LogWarning($"Rule '{_context.FunctionName}' failed: {ex.Message}"); var resp = new HttpResponseMessage(HttpStatusCode.NotImplemented) { Content = new StringContent(ex.Message) }; return(resp); } }
public async Task <HttpResponseMessage> RunAsync(HttpRequestMessage req, CancellationToken cancellationToken) { _log.LogDebug($"Context: {_context.InvocationId} {_context.FunctionName} {_context.FunctionDirectory} {_context.FunctionAppDirectory}"); var ruleName = _context.FunctionName; var aggregatorVersion = GetCustomAttribute <System.Reflection.AssemblyInformationalVersionAttribute>()?.InformationalVersion; _log.LogInformation($"Aggregator v{aggregatorVersion} executing rule '{ruleName}'"); cancellationToken.ThrowIfCancellationRequested(); // Get request body var eventData = await GetWebHookEvent(req); if (eventData == null) { return(req.CreateErrorResponse(HttpStatusCode.BadRequest, "Request body is empty")); } // sanity check if (!DevOpsEvents.IsValidEvent(eventData.EventType) || eventData.PublisherId != DevOpsEvents.PublisherId) { return(req.CreateErrorResponse(HttpStatusCode.BadRequest, "Not a good Azure DevOps post...")); } var eventContext = CreateContextFromEvent(eventData); if (eventContext.IsTestEvent()) { return(req.CreateTestEventResponse(aggregatorVersion, ruleName)); } var configContext = GetConfigurationContext(); var configuration = AggregatorConfiguration.ReadConfiguration(configContext) .UpdateFromUrl(ruleName, req.RequestUri); var logger = new ForwarderLogger(_log); var ruleProvider = new AzureFunctionRuleProvider(logger, _context.FunctionDirectory); var ruleExecutor = new RuleExecutor(logger, configuration); using (_log.BeginScope($"WorkItem #{eventContext.WorkItemPayload.WorkItem.Id}")) { try { var rule = await ruleProvider.GetRule(ruleName); var execResult = await ruleExecutor.ExecuteAsync(rule, eventContext, cancellationToken); if (string.IsNullOrEmpty(execResult)) { return(req.CreateResponse(HttpStatusCode.OK)); } else { _log.LogInformation($"Returning '{execResult}' from '{rule.Name}'"); return(req.CreateResponse(HttpStatusCode.OK, execResult)); } } catch (Exception ex) { _log.LogWarning($"Rule '{ruleName}' failed: {ex.Message}"); return(req.CreateErrorResponse(HttpStatusCode.NotImplemented, ex)); } } }
public async Task <IActionResult> RunAsync(/*HttpRequest request, */ WebHookEvent eventData, CancellationToken cancellationToken) { _log.LogDebug($"Context: {_executionContext.InvocationId} {_executionContext.FunctionName} {_executionContext.FunctionDirectory} {_executionContext.FunctionAppDirectory}"); var ruleName = _executionContext.FunctionName; var aggregatorVersion = RequestHelper.AggregatorVersion; _log.LogInformation($"Aggregator v{aggregatorVersion} executing rule '{ruleName}'"); cancellationToken.ThrowIfCancellationRequested(); if (eventData == null) { return(BadRequest("Request body is empty")); } // sanity check if (!DevOpsEvents.IsValidEvent(eventData.EventType) || eventData.PublisherId != DevOpsEvents.PublisherId) { _log.LogDebug("return BadRequest"); return(BadRequest(new { Error = "Not a good Azure DevOps post..." })); } var helper = new RequestHelper(_log); var eventContext = helper.CreateContextFromEvent(eventData); if (eventContext.IsTestEvent()) { Response.AddCustomHeaders(aggregatorVersion, ruleName); return(RespondToTestEventMessage(aggregatorVersion, ruleName)); } var configContext = GetConfigurationContext(); var configuration = AggregatorConfiguration.ReadConfiguration(configContext) .UpdateFromUrl(ruleName, GetRequestUri()); var logger = new ForwarderLogger(_log); var ruleProvider = new AzureFunctionRuleProvider(logger, _executionContext.FunctionDirectory); var ruleExecutor = new RuleExecutor(logger, configuration); using (_log.BeginScope($"WorkItem #{eventContext.WorkItemPayload.WorkItem.Id}")) { try { var rule = await ruleProvider.GetRule(ruleName); var execResult = await ruleExecutor.ExecuteAsync(rule, eventContext, cancellationToken); if (string.IsNullOrEmpty(execResult)) { return(Ok()); } else { _log.LogInformation($"Returning '{execResult}' from '{rule.Name}'"); return(Ok(execResult)); } } catch (Exception ex) { _log.LogWarning($"Rule '{ruleName}' failed: {ex.Message}"); return(BadRequest(ex.Message)); } } }
public async Task <HttpResponseMessage> Run(HttpRequestMessage req) { log.LogDebug($"Context: {context.InvocationId} {context.FunctionName} {context.FunctionDirectory} {context.FunctionAppDirectory}"); var aggregatorVersion = GetCustomAttribute <System.Reflection.AssemblyInformationalVersionAttribute>()?.InformationalVersion; try { string rule = context.FunctionName; log.LogInformation($"Aggregator v{aggregatorVersion} executing rule '{rule}'"); } catch (Exception ex) { log.LogWarning($"Failed parsing request headers: {ex.Message}"); } // Get request body string jsonContent = await req.Content.ReadAsStringAsync(); if (string.IsNullOrWhiteSpace(jsonContent)) { log.LogWarning($"Failed parsing request body: empty"); var resp = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent("Request body is empty") }; return(resp); } dynamic data = JsonConvert.DeserializeObject(jsonContent); string eventType = data.eventType; // sanity check if (!DevOpsEvents.IsValidEvent(eventType) || data.publisherId != DevOpsEvents.PublisherId) { return(req.CreateResponse(HttpStatusCode.BadRequest, new { error = "Not a good Azure DevOps post..." })); } var config = new ConfigurationBuilder() .SetBasePath(context.FunctionAppDirectory) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var configuration = AggregatorConfiguration.Read(config); var logger = new ForwarderLogger(log); var wrapper = new RuleWrapper(configuration, logger, context.FunctionName, context.FunctionDirectory); try { string execResult = await wrapper.Execute(data); if (string.IsNullOrEmpty(execResult)) { var resp = new HttpResponseMessage(HttpStatusCode.OK); return(resp); } else { log.LogInformation($"Returning '{execResult}' from '{context.FunctionName}'"); var resp = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(execResult) }; return(resp); } } catch (Exception ex) { log.LogWarning($"Rule '{context.FunctionName}' failed: {ex.Message}"); var resp = new HttpResponseMessage(HttpStatusCode.NotImplemented) { Content = new StringContent(ex.Message) }; return(resp); } }