/// <inheritdoc cref="SierraActor{T}" /> public override async Task <VstsBuildDefinition> Add(VstsBuildDefinition model) { var templateDefinition = model.SourceCode.ProjectType == ProjectTypeEnum.WebApi ? _vstsConfiguration.WebApiBuildDefinitionTemplate : _vstsConfiguration.WebUIBuildDefinitionTemplate; //load template var template = await _buildHttpClient.GetDefinitionAsync(_vstsConfiguration.VstsTargetProjectId, templateDefinition.DefinitionId, templateDefinition.RevisionId); //customize the template template.Name = model.ToString(); template.Repository.Id = model.SourceCode.RepoVstsId.ToString(); //push to vsts var vstsDefinition = await _buildHttpClient.CreateOrUpdateDefinition(template, _vstsConfiguration.VstsTargetProjectId); //update model model.UpdateWithVstsDefinition(vstsDefinition.Id); _bigBrother.Publish(new BuildDefinitionCreated { DefinitionName = vstsDefinition.Name }); return(model); }
/// <inheritdoc /> public async Task <ILease> ReadByLeaseTypeAsync(string leaseType) { return(await _retryPolicy.ExecuteAsync(async() => { try { var query = _documentClient.CreateDocumentQuery <CosmosDbLease>( UriFactory.CreateDocumentCollectionUri(_options.Value.Database, _options.Value.LeasesCollection), new FeedOptions { ConsistencyLevel = _options.Value.ConsistencyLevel }) .Where(so => so.LeaseType == leaseType) .AsDocumentQuery(); var feedResponse = await query.ExecuteNextAsync <CosmosDbLease>(); return feedResponse.FirstOrDefault(); } catch (Exception e) { _telemetry.Publish(e.ToExceptionEvent()); throw; } }).ConfigureAwait(false)); }
private async Task DistributeToService(Service service, InflightMessage message, CancellationToken cancelToken) { //here we have to identify APIs - ultimately by name but naming is not consistent at the moment //single partition only var parts = await QueryManager.GetPartitionListAsync(service.ServiceName); if (parts.Count == 0 && IsNullOrWhiteSpace(parts.ContinuationToken)) { return; } if (parts.Count > 1 || !IsNullOrWhiteSpace(parts.ContinuationToken)) //there is more than 1 partition { return; } var partition = parts.First(); cancelToken.ThrowIfCancellationRequested(); var replicas = await QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id); //stateless service - so no secondary replicas if (replicas == null || replicas.Count == 0 || !replicas.All(r => r.HealthState == HealthState.Ok || r.HealthState == HealthState.Warning)) { //all considered unhealthy, do not try to ping them even _bb?.Publish(GetServiceReplicaAlert(service, "No healthy replica found")); return; } await Task.WhenAll(replicas.Select(r => DistributeToReplica(service, r, message, cancelToken))); }
public async Task <Guid> DoWork(string payload, string type) { // need to handle the possibility of the resources in the pool being all busy! try { var handlerId = _free.Value.First(); var handle = Guid.NewGuid(); _free.Value.Remove(handlerId); _busy.Value.Add( handle, new MessageHook { HandlerId = handlerId, Type = type }); await StateManager.AddOrUpdateStateAsync(nameof(_free), _free.Value, (s, value) => value); await StateManager.AddOrUpdateStateAsync(nameof(_busy), _busy.Value, (s, value) => value); await ActorProxy.Create <IEventHandlerActor>(new ActorId(handlerId)).Handle(handle, payload, type); return(handle); } catch (Exception e) { _bigBrother.Publish(e.ToExceptionEvent()); throw; } }
/// <summary> /// add new release definition by cloning the template /// </summary> /// <param name="model">release definition model</param> /// <returns>updated release definition model</returns> public override async Task <VstsReleaseDefinition> Add(VstsReleaseDefinition model) { var templateConfig = model.BuildDefinition.SourceCode.ProjectType == ProjectTypeEnum.WebApi ? model.RingBased ? _vstsConfiguration.WebApiRingReleaseDefinitionTemplate : _vstsConfiguration.WebApiReleaseDefinitionTemplate : model.RingBased ? _vstsConfiguration.WebUIRingReleaseDefinitionTemplate : _vstsConfiguration.WebUIReleaseDefinitionTemplate; //create (or locate) var clone = await ClonePipeline(model, templateConfig); //customize if (!model.RingBased) { await CustomizeNonRingPipeline(model, clone); } else { CustomizeRingPipeline(model, clone); } //persist (or update) var vstsDef = await _releaseHttpClient.CreateOrResetDefinition(clone, _vstsConfiguration.VstsTargetProjectId); model.UpdateWithVstsReleaseDefinition(vstsDef.Id); _bigBrother.Publish(new ReleaseDefinitionCreated { DefinitionName = model.ToString() }); return(model); }
public override async Task <ResourceGroup> Add(ResourceGroup model) { var azure = _azureFactory[model.Environment]; IResourceGroup resourceGroup; if (await azure.ResourceGroups.ContainAsync(model.Name)) { resourceGroup = await azure.ResourceGroups.GetByNameAsync(model.Name); } else { resourceGroup = await azure.ResourceGroups .Define(model.Name) .WithRegion(Region.EuropeNorth) .CreateAsync(); _bigBrother.Publish(new ResourceGroupCreated { EnvironmentName = model.Environment.ToString(), RegionName = resourceGroup.RegionName, ResourceId = resourceGroup.Id, ResourceGroupName = resourceGroup.Name, }); } model.State = EntityStateEnum.Created; model.ResourceId = resourceGroup.Id; return(model); }
private async Task <TimeSpan> OperationTelemetryHandler(Func <CancellationToken, Task <TimeSpan> > operation, CancellationToken token, [CallerMemberName] string memberName = "") { try { var operationEvent = new OperationTelemetryEvent(memberName); var result = await operation(token).ConfigureAwait(false); _telemetry.Publish(operationEvent); return(result); } catch (OperationCanceledException _) { _telemetry.Publish(new LeaseStoppedEvent(InstanceId, _options.Value.WorkerType, _options.Value.Priority)); throw; } catch (Exception ex) { _timer.Dispose(); _telemetry.Publish(new LeaseExceptionEvent(InstanceId, _options.Value.WorkerType, _options.Value.Priority, ex.Message)); throw new WorkerLeaseException( $"An unhandled exception occurred executing operation [{memberName}]", ex); } }
/// <summary> /// /// </summary> /// <typeparam name="TRequest"></typeparam> /// <param name="request"></param> /// <param name="metadata"></param> /// <returns></returns> public virtual async Task Call <TRequest>(TRequest request, IDictionary <string, object> metadata = null) { try { if (!(request is MessageData messageData)) { throw new Exception("injected wrong implementation"); } //make a call to client identity provider if (WebhookConfig.AuthenticationConfig.Type != AuthenticationType.None) { await AcquireTokenHandler.GetToken(_client); } var uri = RequestBuilder.BuildUri(WebhookConfig, messageData.Payload); var httpVerb = RequestBuilder.SelectHttpVerb(WebhookConfig, messageData.Payload); var payload = this.RequestBuilder.BuildPayload(this.WebhookConfig, messageData.Payload, metadata); void TelemetryEvent(string msg) { BigBrother.Publish(new HttpClientFailure(messageData.Handle, messageData.Type, payload, msg)); } var response = await _client.ExecuteAsJsonReliably(httpVerb, uri, payload, TelemetryEvent); BigBrother.Publish(new WebhookEvent(messageData.Handle, messageData.Type, $"Response status code {response.StatusCode}")); } catch (Exception e) { BigBrother.Publish(e.ToExceptionEvent()); throw; } }
/// <inheritdoc /> public virtual async Task <string> GetTokenAsync(CancellationToken cancellationToken) { //get initial access token and refresh token if (OidcAuthenticationToken.AccessToken == null) { BigBrother.Publish(new ClientTokenRequest { ClientId = OidcAuthenticationConfig.ClientId, Authority = OidcAuthenticationConfig.Uri, Message = "Token is null getting a new one." }); await EnterSemaphore(cancellationToken, async() => { var httpClient = HttpClientFactory.Get(OidcAuthenticationConfig.Uri); var response = await GetTokenResponseAsync(httpClient, cancellationToken); ReportTokenUpdateFailure(OidcAuthenticationConfig, response); UpdateToken(response); BigBrother.Publish(new ClientTokenRequest { ClientId = OidcAuthenticationConfig.ClientId, Authority = OidcAuthenticationConfig.Uri, Message = "Got a new token and updating the http client when token was null" }); }); } else if (CheckExpired()) { await EnterSemaphore(cancellationToken, async() => { if (CheckExpired()) { var httpClient = HttpClientFactory.Get(OidcAuthenticationConfig.Uri); var response = await GetTokenResponseAsync(httpClient, cancellationToken); ReportTokenUpdateFailure(OidcAuthenticationConfig, response); UpdateToken(response); BigBrother.Publish(new ClientTokenRequest { ClientId = OidcAuthenticationConfig.ClientId, Authority = OidcAuthenticationConfig.Uri, Message = "Refreshing token and updating the http client with new token" }); } }); } return($"Bearer {OidcAuthenticationToken.AccessToken}"); }
/// <summary> /// This method is called whenever an actor is activated. /// An actor is activated the first time any of its methods are invoked. /// </summary> protected override async Task OnActivateAsync() { _bigBrother.Publish(new ActorActivated(this)); var names = (await StateManager.GetStateNamesAsync()).Take(1).ToList(); if (names.Any()) { _handleTimer = RegisterTimer( InternalHandle, names.FirstOrDefault(), TimeSpan.FromMilliseconds(100), TimeSpan.MaxValue); } }
/// <inheritdoc /> /// <summary> /// This is the main entry point for your service replica. /// This method executes when this replica of your service becomes primary and has write status. /// </summary> /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param> protected override async Task RunAsync(CancellationToken cancellationToken) { InitInflightQueue(); while (true) { cancellationToken.ThrowIfCancellationRequested(); try { using (var tx = StateManager.CreateTransaction()) { var message = await _inflightQueue.TryDequeueAsync(tx, cancellationToken); if (message.HasValue) { await _clusterNotifier.DistributeToCluster(message.Value, cancellationToken, Context.CodePackageActivationContext.ApplicationName); } await tx.CommitAsync(); } } catch (OperationCanceledException) //cancellation requested { throw; } catch (Exception e) //anything else { _bigBrother.Publish(e.ToExceptionEvent()); } await Task.Delay(WaitTimeBetweenLoop, cancellationToken); } // ReSharper disable once FunctionNeverReturns }
/// <inheritdoc /> public void Initialize(ITelemetry telemetry) { if (!(telemetry is RequestTelemetry requestTelemetry)) { return; } if (_httpContextAccessor?.HttpContext?.Request == null) { return; } var request = _httpContextAccessor.HttpContext.Request; try { if (string.IsNullOrEmpty(requestTelemetry.ResponseCode)) { HandleIncomingRequest(request.Path.Value, requestTelemetry, request); } else { HandleCompletedRequest(request.Path.Value, requestTelemetry, request); } } catch (Exception e) { _bigBrother.Publish(e.ToExceptionEvent()); } }
/// <summary> /// /// </summary> /// <typeparam name="TRequest"></typeparam> /// <param name="request"></param> /// <param name="metadata"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public virtual async Task CallAsync <TRequest>(TRequest request, IDictionary <string, object> metadata, CancellationToken cancellationToken) { try { if (!(request is MessageData messageData)) { throw new Exception("injected wrong implementation"); } //todo refactor into a single call and a dto var uri = RequestBuilder.BuildUri(WebhookConfig, messageData.Payload); var httpMethod = RequestBuilder.SelectHttpMethod(WebhookConfig, messageData.Payload); var originalPayload = RequestBuilder.BuildPayload(WebhookConfig, messageData.Payload, metadata); var payload = WebhookConfig.PayloadTransformation == PayloadContractTypeEnum.WrapperContract ? WrapPayload(originalPayload, WebhookConfig, messageData) : originalPayload; var config = RequestBuilder.SelectWebhookConfig(WebhookConfig, messageData.Payload); var headers = RequestBuilder.GetHttpHeaders(WebhookConfig, messageData); var authenticationConfig = RequestBuilder.GetAuthenticationConfig(WebhookConfig, messageData.Payload); var httpClient = HttpClientFactory.Get(config); await AddAuthenticationHeaderAsync(cancellationToken, authenticationConfig, headers); var response = await httpClient.SendRequestReliablyAsync(httpMethod, uri, headers, payload, cancellationToken); await _requestLogger.LogAsync(httpClient, response, messageData, uri, httpMethod, headers); } catch (Exception e) { BigBrother.Publish(e.ToExceptionEvent()); throw; } }
public void EntryPoint_PushTimed() { IBigBrother bb = BigBrother.CreateDefault(DevKey, DevKey).DeveloperMode(); bb.Publish(new TestTimedEvent()); bb.Flush(); }
/// <inheridoc/> public override async Task <SourceCodeRepository> Add(SourceCodeRepository sourceCodeRepository) { //if fork not requested, look up the repo id if (!sourceCodeRepository.Fork) { var gitRepo = await _gitClient.LoadGitRepositoryIfExists(sourceCodeRepository.SourceRepositoryName); if (gitRepo == null) { throw new ArgumentException( $"Repository {sourceCodeRepository.SourceRepositoryName} does not exist", nameof(SourceCodeRepository)); } sourceCodeRepository.UpdateWithVstsRepo(gitRepo.Id); return(sourceCodeRepository); } //otherwise fork to a new repo var repo = await _gitClient.CreateForkIfNotExists(_vstsConfiguration.VstsCollectionId, _vstsConfiguration.VstsTargetProjectId, sourceCodeRepository); if (!repo.IsFork) { _bigBrother.Publish(new ForkRequestFailed { ForkName = repo.Name, Message = $"Repository already exists but is not a fork" }); } else { sourceCodeRepository.UpdateWithVstsRepo(repo.Id); _bigBrother.Publish(new ForkRequestSucceeded { ForkName = repo.Name }); return(sourceCodeRepository); } return(null); }
protected override async Task OnActivateAsync() { try { _bigBrother.Publish(new ActorActivated(this)); var inHandlers = await StateManager.TryGetStateAsync <Dictionary <Guid, string> >(nameof(_messagesInHandlers)); if (inHandlers.HasValue) { _messagesInHandlers = inHandlers; } else { _messagesInHandlers = new ConditionalValue <Dictionary <Guid, string> >(true, new Dictionary <Guid, string>()); await StateManager.AddOrUpdateStateAsync(nameof(_messagesInHandlers), _messagesInHandlers.Value, (s, value) => value); } await SetupServiceBus(); _receiver = new MessageReceiver( _settings.ServiceBusConnectionString, EntityNameHelper.FormatSubscriptionPath(TypeExtensions.GetEntityName(Id.GetStringId()), SubscriptionName), ReceiveMode.PeekLock, new RetryExponential(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(500), 3), BatchSize); _poolTimer = new Timer(ReadEvents, null, TimeSpan.FromMilliseconds(1000), TimeSpan.FromMilliseconds(100)); } catch (Exception e) { _bigBrother.Publish(e.ToExceptionEvent()); throw; } await base.OnActivateAsync(); }
public async Task LogAsync( HttpClient httpClient, HttpResponseMessage response, MessageData messageData, Uri uri, HttpMethod httpMethod, WebHookHeaders headers ) { _bigBrother.Publish(new WebhookEvent( messageData.EventHandlerActorId, messageData.Type, $"Response status code {response.StatusCode}", uri.AbsoluteUri, httpMethod, response.StatusCode, messageData.CorrelationId)); //only log the failed requests in more depth, need to have a good think about this - debugging v privacy if (response.IsSuccessStatusCode) { return; } _bigBrother.Publish(new FailedWebHookEvent( httpClient.DefaultRequestHeaders.ToString(), response.Headers.ToString(), messageData.Payload ?? string.Empty, await GetPayloadAsync(response), messageData.EventHandlerActorId, messageData.Type, $"Response status code {response.StatusCode}", uri.AbsoluteUri, httpMethod, response.StatusCode, messageData.CorrelationId) { AuthToken = response.StatusCode == System.Net.HttpStatusCode.Unauthorized? headers?.RequestHeaders?[Constants.Headers.Authorization]: string.Empty }); }
public void EntryPoint_PushAnonymous() { IBigBrother bb = BigBrother.CreateDefault(DevKey, DevKey).DeveloperMode(); bb.Publish(new { SomeStuff = Lorem.GetSentence(), SomeMoreStuff = Lorem.GetSentence(), AndEvenMoreStuff = Lorem.GetSentence() }); bb.Flush(); }
private AsyncRetryPolicy CreateRetryPolicy() { return(Policy .Handle <DocumentClientException>(e => e.RetryAfter > TimeSpan.Zero) .WaitAndRetryAsync(5, (count, exception, context) => ((DocumentClientException)exception).RetryAfter, (exception, timeSpan, count, context) => { _telemetry.Publish(new CosmosRetryEvent(timeSpan, count)); return Task.CompletedTask; } )); }
public IActionResult Post([FromBody] Record value) { if (string.IsNullOrWhiteSpace(value.Name) || string.IsNullOrWhiteSpace(value.Address)) { return(BadRequest()); } var id = new Random().Next(ExistingRecordsRange + 1, 1000); _bb.Publish(new ValueAddedEvent(id)); return(Created($"/api/values/{id}", id)); }
public void EntryPoint_PushException() { const string message = "KABOOM!!!"; IBigBrother bb = BigBrother.CreateDefault(DevKey, DevKey).DeveloperMode(); try { BlowUp(message); } catch (Exception ex) { bb.Publish(ex.ToExceptionEvent()); bb.Flush(); } }
private async Task PrepareActorCall(HttpContext context, PathString remaining) { try { // as per rfc, this may contain charset (and indeed other parameters) if (!context.Request.ContentType.StartsWith("application/json", StringComparison.InvariantCultureIgnoreCase)) { throw new ActorCallFailedException("only the application/json content type is accepted"); } var actorMethod = FindActorMethod(remaining); var jsonSerializedParameter = await ReadAsStringAsync(context.Request.Body); var parameterValue = JsonConvert.DeserializeObject(jsonSerializedParameter, actorMethod.Parameter.ParameterType); var actorId = context.Request.Query["actorId"]; var result = await CallActor(actorId, actorMethod.InterfaceType, actorMethod.Method, parameterValue); if (result != null) { context.Response.ContentType = "application/json"; var resultJson = JsonConvert.SerializeObject(result); await context.Response.WriteAsync(resultJson); } else { context.Response.StatusCode = (int)HttpStatusCode.NoContent; } } catch (Exception ex) { _bigBrother.Publish(ex.ToExceptionEvent()); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; var error = new { errors = ListInnerExceptions(ex) .Where(x => !(x is AggregateException ag && ag.InnerExceptions.Count == 1)) .Select(x => new { message = x.Message, type = x.GetType().FullName }) }; context.Response.ContentType = "application/json"; await context.Response.WriteAsync(JsonConvert.SerializeObject(error)); } }
/// <summary> /// Handles exceptions by populating the response inside the <see cref="HttpContext"/> depending on /// which type of exception is being handled. /// </summary> /// <param name="context">The HTTP-specific information about an individual HTTP request.</param> /// <param name="exception"></param> /// <returns>[ASYNC] <see cref="Task"/> future promise.</returns> /// <remarks> /// This method will unwrap any <see cref="AggregateException"/> until it finds a regular exception /// and then process the regular exception through the pipeline. /// </remarks> internal virtual async Task HandleException(HttpContext context, Exception exception) { if (context.Response.HasStarted) { Bb.Publish(new ResponseAlreadyStartedExceptionEvent { Exception = exception }); return; } // Continuously unwrap AggregateException while (exception is AggregateException aex) { if (aex.InnerExceptions.Any()) { exception = aex.InnerExceptions.First(); } else { break; } } string result; context.Response.ContentType = "application/json"; if (exception is BadRequestException badRequest) { result = JsonConvert.SerializeObject(badRequest.ToResponse()); context.Response.StatusCode = (int)HttpStatusCode.BadRequest; } else { result = JsonConvert.SerializeObject( new ErrorResponse { #if DEBUG Message = exception.Message, StackTrace = exception.StackTrace #else Message = "Sorry, but something bad happened!" #endif });
public async Task <IActionResult> Post([FromBody] JObject payload, string type) { var proxyFactory = new ServiceProxyFactory((c) => new FabricTransportActorRemotingClientFactory( fabricTransportRemotingSettings: null, callbackMessageHandler: c, serializationProvider: new ServiceRemotingJsonSerializationProvider())); var service = proxyFactory.CreateServiceProxy <IBullfrogNotificationBackendService>( new Uri("fabric:/ISummonNoobs/ISummonNoobsBackendService"), new ServicePartitionKey(1)); //TODO: review keying strategy await service.IngestMessage(type, payload); _bigBrother.Publish(new MessagedIngested { MessageType = type, Payload = payload.ToString() }); return(Ok()); }
protected override async Task OnOpenAsync(ReplicaOpenMode openMode, CancellationToken cancellationToken) { _bigBrother.Publish(new ServiceActivatedEvent(Context, InFlightMessageCount)); await base.OnOpenAsync(openMode, cancellationToken); }
/// <inheritdoc /> public async Task <ILease> AllocateLeaseAsync(Guid instanceId, CancellationToken token) { _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType, _options.Value.Priority, $"Lease allocation started for instance {instanceId}")); var lease = await _leaseStore.ReadByLeaseTypeAsync(_options.Value.WorkerType).ConfigureAwait(false); if (lease?.LeasedUntil != null && lease.LeasedUntil.Value > ServerDateTime.UtcNow) { if (lease.InstanceId == instanceId) { _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType, _options.Value.Priority, $"Existing lease reused: {GenerateLeaseInfo(lease)}")); return(lease); } return(null); } await _leaseStore.AddLeaseRequestAsync(new LeaseRequest { LeaseType = _options.Value.WorkerType, Priority = _options.Value.Priority, InstanceId = instanceId, TimeToLive = 2 * _options.Value.ElectionDelay.Seconds }).ConfigureAwait(false); // backoff to allow other workers to add their lease request await Task.Delay(_options.Value.ElectionDelay, token); _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType, _options.Value.Priority, $"Leader election starting")); var winnerInstanceId = await _leaseStore.SelectWinnerRequestAsync(_options.Value.WorkerType); if (!winnerInstanceId.HasValue) { //This should not happen normally _telemetry.Publish(new WinnerNotExistingEvent(instanceId, _options.Value.WorkerType)); return(null); } if (winnerInstanceId != instanceId) { _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType, _options.Value.Priority, $"Lease failed to be acquired after election. Winner instance is {winnerInstanceId.Value}.")); return(null); } if (lease == null) { lease = new Lease { LeaseType = _options.Value.WorkerType }; } var now = ServerDateTime.UtcNow; lease.InstanceId = instanceId; lease.Priority = _options.Value.Priority; lease.Interval = _slottedInterval.Calculate(now, _options.Value.LeaseInterval); lease.LeasedUntil = now.Add(lease.Interval.Value); var persistResult = await TryPersistLease(lease).ConfigureAwait(false); return(persistResult.Lease); }
public override async Task <ManagedIdentity> Add(ManagedIdentity model) { // TODO: remove this custom error logging when a more generic solution is available var stage = "initialization"; string subscriptionId = null; try { var azure = _azureFactory[model.Environment]; subscriptionId = azure.SubscriptionId; stage = "resourceGroupValidation"; var resourceGroup = await azure.ResourceGroups.GetByNameAsync(model.ResourceGroupName); stage = "identityFinding"; var identities = await azure.Identities.ListByResourceGroupAsync(model.ResourceGroupName); var identity = identities.FirstOrDefault(x => x.Name == model.IdentityName); if (identity == null) { stage = "identityCreation"; identity = await azure.Identities .Define(model.IdentityName) .WithRegion(resourceGroup.RegionName) .WithExistingResourceGroup(resourceGroup) .CreateAsync(); } model.IdentityId = identity.Id; stage = "scaleSetValidation"; var scaleSets = await azure.VirtualMachineScaleSets.ListAsync(); stage = "scaleSetIdentityAssignment"; Task AssignIdentityToScaleSet(IVirtualMachineScaleSet scaleSet) => GetActor <IScaleSetIdentityActor>(ScaleSetIdentityActor.ActorIdPrefix + scaleSet.Id) .Add(new ScaleSetIdentity { Environment = model.Environment, ManagedIdentityId = identity.Id, }); var scaleSetAssignmentTasks = scaleSets.Select(AssignIdentityToScaleSet); await Task.WhenAll(scaleSetAssignmentTasks); model.State = EntityStateEnum.Created; return(model); } catch (Exception e) { var errorEvent = new ManagedIdentityActorError(e) { Stage = stage, SubscriptionId = subscriptionId, EnvironmentName = model.Environment.ToString(), IdentityName = model.IdentityName, ResourceGroupName = model.ResourceGroupName, }; _bigBrother.Publish(errorEvent); throw; } }
/// <summary> /// configure services to be used by the asp.net runtime /// </summary> /// <param name="services">service collection</param> /// <returns>service provider instance (Autofac provider)</returns> public IServiceProvider ConfigureServices(IServiceCollection services) { try { services.AddApplicationInsightsTelemetry(AppSettings.Telemetry.InstrumentationKey); ConfigureDatabase(services); services.AddCors(options => { options.AddPolicy("CorsPolicy", cpb => cpb .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); }); services.AddMvc(options => { var policy = ScopePolicy.Create(AppSettings.ServiceConfigurationOptions.RequiredScopes.ToArray()); options.Filters.Add(new AuthorizeFilter(policy)); }); services.AddApiVersioning( o => { o.ReportApiVersions = true; o.AssumeDefaultVersionWhenUnspecified = true; o.DefaultApiVersion = new ApiVersion(1, 0); }); services.AddSwaggerGen(c => { c.IncludeXmlComments("WebApi.Template.xml"); c.DescribeAllEnumsAsStrings(); c.SwaggerDoc("v1", new Info { Version = "1.0.0", Title = "WebApi.Template" }); c.CustomSchemaIds(x => x.FullName); c.AddSecurityDefinition("Bearer", new ApiKeyScheme { In = "header", Description = "Please insert JWT with Bearer into field", Name = "Authorization", Type = "apiKey" }); }); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddIdentityServerAuthentication(x => { x.ApiName = AppSettings.ServiceConfigurationOptions.ApiName; x.SupportedTokens = SupportedTokens.Jwt; x.RequireHttpsMetadata = AppSettings.ServiceConfigurationOptions.IsHttps; x.Authority = AppSettings.ServiceConfigurationOptions.Authority; x.RequireHttpsMetadata = AppSettings.ServiceConfigurationOptions.IsHttps; //TODO: this requires Eshopworld.Beatles.Security to be refactored //x.AddJwtBearerEventsTelemetry(bb); }); services.AddMvc().AddFluentValidation(fvc => fvc.RegisterValidatorsFromAssemblyContaining <NameAddressesValidator>()); var builder = new ContainerBuilder(); builder.Populate(services); builder.RegisterInstance(_bb).As <IBigBrother>().SingleInstance(); builder.RegisterInstance(AppSettings).AsSelf().SingleInstance(); // add additional services or modules into container here var container = builder.Build(); return(new AutofacServiceProvider(container)); } catch (Exception e) { _bb.Publish(e.ToBbEvent()); throw; } }
/// <summary> /// configure services to be used by the asp.net runtime /// </summary> /// <param name="services">service collection</param> /// <returns>service provider instance (Autofac provider)</returns> public IServiceProvider ConfigureServices(IServiceCollection services) { try { services.AddApplicationInsightsTelemetry(_telemetrySettings.InstrumentationKey); services.Configure <ServiceConfigurationOptions>(_configuration.GetSection("ServiceConfigurationOptions")); var serviceConfigurationOptions = services.BuildServiceProvider() .GetService <IOptions <ServiceConfigurationOptions> >(); services.AddMvc(options => { var filter = #if (DEBUG) new AllowAnonymousFilter(); #else var policy = ScopePolicy.Create(serviceConfigurationOptions.Value.RequiredScopes.ToArray()); (IFilterMetadata) new AuthorizeFilter(policy) : #endif options.Filters.Add(filter); }); services.AddApiVersioning(); //Get XML documentation var path = Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"); //if not generated throw an event but it's not going to stop the app from starting if (!File.Exists(path)) { BigBrother.Write(new Exception("Swagger XML document has not been included in the project")); } else { services.AddSwaggerGen(c => { c.IncludeXmlComments(path); c.DescribeAllEnumsAsStrings(); c.SwaggerDoc("v1", new OpenApiInfo { Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(), Title = "ISummonNoobs" }); c.CustomSchemaIds(x => x.FullName); c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Please insert JWT with Bearer into field", Type = UseOpenApiV2 ? SecuritySchemeType.ApiKey : SecuritySchemeType.Http, Scheme = "bearer", BearerFormat = "JWT", }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, }, new string[0] } }); }); } services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddIdentityServerAuthentication( x => { x.ApiName = serviceConfigurationOptions.Value.ApiName; x.ApiSecret = serviceConfigurationOptions.Value.ApiSecret; x.Authority = serviceConfigurationOptions.Value.Authority; x.RequireHttpsMetadata = serviceConfigurationOptions.Value.IsHttps; //TODO: this requires Eshopworld.Beatles.Security to be refactored //x.AddJwtBearerEventsTelemetry(bb); }); var builder = new ContainerBuilder(); builder.Populate(services); builder.RegisterInstance(_bb).As <IBigBrother>().SingleInstance(); // add additional services or modules into container here var container = builder.Build(); return(new AutofacServiceProvider(container)); } catch (Exception e) { _bb.Publish(e.ToExceptionEvent()); throw; } }
/// <summary> /// This is the main entry point for your service replica. /// This method executes when this replica of your service becomes primary and has write status. /// </summary> /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param> protected override async Task RunAsync(CancellationToken cancellationToken) { // TODO: Check fabric node topology - if running below Bronze, set min and target replicas to 1 instead of 3 try { var serviceList = (await _fabricClient.QueryManager.GetServiceListAsync(new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"))) .Select(s => s.ServiceName.AbsoluteUri) .ToList(); if (!serviceList.Contains(ServiceNaming.EventHandlerServiceFullName)) { await _fabricClient.ServiceManager.CreateServiceAsync( new StatefulServiceDescription { ApplicationName = new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"), HasPersistedState = true, MinReplicaSetSize = _defaultServiceSettings.DefaultMinReplicaSetSize, TargetReplicaSetSize = _defaultServiceSettings.DefaultTargetReplicaSetSize, PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(10), ServiceTypeName = ServiceNaming.EventHandlerActorServiceType, ServiceName = new Uri(ServiceNaming.EventHandlerServiceFullName), PlacementConstraints = _defaultServiceSettings.DefaultPlacementConstraints }, TimeSpan.FromSeconds(30), cancellationToken); } foreach (var @event in _eventHandlersConfig) { foreach (var sub in @event.AllSubscribers) { sub.EventType = @event.Type; if (cancellationToken.IsCancellationRequested) { return; } var readerServiceNameUri = ServiceNaming.EventReaderServiceFullUri(@event.Type, sub.SubscriberName, sub.DLQMode != null); if (!serviceList.Contains(readerServiceNameUri)) { await _fabricClient.ServiceManager.CreateServiceAsync( new StatefulServiceDescription { ApplicationName = new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"), HasPersistedState = true, MinReplicaSetSize = _defaultServiceSettings.DefaultMinReplicaSetSize, TargetReplicaSetSize = _defaultServiceSettings.DefaultTargetReplicaSetSize, PartitionSchemeDescription = new SingletonPartitionSchemeDescription(), ServiceTypeName = ServiceNaming.EventReaderServiceType, ServiceName = new Uri(readerServiceNameUri), InitializationData = Encoding.UTF8.GetBytes(EventReaderInitData.GetReaderInitDataAsString(sub)), PlacementConstraints = _defaultServiceSettings.DefaultPlacementConstraints }, TimeSpan.FromSeconds(30), cancellationToken); } } } // TODO: Can't do this for internal eshopworld.com|net hosts, otherwise the sharding would be crazy - need to aggregate internal hosts by domain //var uniqueHosts = Rules.Select(r => new Uri(r.HookUri).Host).Distinct(); //var dispatcherServiceList = (await FabricClient.QueryManager.GetServiceListAsync(new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"))) // .Select(s => s.ServiceName.AbsoluteUri) // .ToList(); //todo this might be used for dispatchers per host but that seems a bit drastic //foreach (var host in uniqueHosts) //{ // if (cancellationToken.IsCancellationRequested) return; // var dispatcherServiceNameUri = $"fabric:/{Constants.CaptainHookApplication.ApplicationName}/{Constants.CaptainHookApplication.EventDispatcherServiceName}.{host}"; // if (dispatcherServiceList.Contains(dispatcherServiceNameUri)) continue; // await FabricClient.ServiceManager.CreateServiceAsync( // new StatefulServiceDescription // { // ApplicationName = new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"), // HasPersistedState = true, // DefaultMinReplicaSetSize = 3, // TargetReplicaSetSize = 3, // PartitionSchemeDescription = new SingletonPartitionSchemeDescription(), // ServiceTypeName = Constants.CaptainHookApplication.EventReaderServiceType, // ServiceName = new Uri(dispatcherServiceNameUri), // InitializationData = Encoding.UTF8.GetBytes(host) // }); //} } catch (Exception ex) { _bigBrother.Publish(ex.ToExceptionEvent()); throw; } }