private async Task <ResourceControllerResult?> CheckService(V1Service entity) { if (entity.GetAnnotation(ServiceAnnotation) == null) { _logger.LogInformation($"Service {entity.Name()} has no wirepact annotation."); return(null); } var targetPort = Convert.ToInt32(entity.GetAnnotation(DeploymentAnnotation)); if (entity.Spec.Ports.Any(p => p.Port == targetPort && p.TargetPort == "envoy")) { _logger.LogInformation($"Service {entity.Name()} has envoy target set."); return(null); } var port = entity.Spec.Ports.FirstOrDefault(p => p.Port == targetPort); if (port == null) { _logger.LogInformation($"Service {entity.Name()} has no port to the target."); return(null); } port.TargetPort = "envoy"; _logger.LogInformation($"Update Service {entity.Name()}."); await _client.Update(entity); return(null); }
public async Task RegisterFinalizerAsync <TFinalizer>(TEntity entity) where TFinalizer : IResourceFinalizer <TEntity> { using var scope = _services.CreateScope(); var finalizer = scope.ServiceProvider.GetRequiredService <TFinalizer>(); _logger.LogTrace( @"Try to add finalizer ""{finalizer}"" on entity ""{kind}/{name}"".", finalizer.Identifier, entity.Kind, entity.Name()); if (entity.AddFinalizer(finalizer.Identifier)) { _logger.LogInformation( @"Added finalizer ""{finalizer}"" on entity ""{kind}/{name}"".", finalizer.Identifier, entity.Kind, entity.Name()); } await _client.Update(entity); }
/// <summary> /// Check the <see cref="V1Lease"/> object for the leader election. /// </summary> /// <returns>A Task.</returns> internal async Task CheckLeaderLease() { if (_namespace.Length == 0) { _logger.LogTrace("Fetching namespace for leader election."); _namespace = await _client.GetCurrentNamespace(); } _logger.LogTrace(@"Fetch V1Lease object for operator ""{operator}"".", _settings.Name); var lease = await _client.Get <V1Lease>(_leaseName, _namespace); // If the lease does not exist, create it, set this instance as leader // fire the appropriate event, return. if (lease == null) { _logger.LogInformation( @"There was no lease for operator ""{operator}"". Creating one and electing ""{hostname}"" as leader.", _settings.Name, _hostname); try { await _client.Create( new V1Lease( $"{V1Lease.KubeGroup}/{V1Lease.KubeApiVersion}", V1Lease.KubeKind, new V1ObjectMeta( name: _leaseName, namespaceProperty: _namespace, annotations: new Dictionary <string, string> { { "leader-elector", _settings.Name } }), new V1LeaseSpec( DateTime.UtcNow, _hostname, _settings.LeaderElectionLeaseDuration, 0, DateTime.UtcNow))); _election.LeadershipChanged(LeaderState.Leader); } catch (HttpOperationException e) when(e.Response.StatusCode == HttpStatusCode.Conflict) { _logger.LogInformation("Another instance of the operator was faster. Falling back to candiate."); _election.LeadershipChanged(LeaderState.Candidate); } catch (HttpOperationException ex) { _logger.LogCritical( ex, @"A http error happened during leader election check of instance ""{hostname}"" of operator ""{operator}"". Response Message: ""{response}""", _hostname, _settings.Name, $"Phrase: {ex.Response.ReasonPhrase}\nContent: {ex.Response.Content}"); } catch (Exception ex) { _logger.LogCritical( ex, @"A generic error happened during leader election check of instance ""{hostname}"" of operator ""{operator}"".", _hostname, _settings.Name); } return; } /* * If the lease exists, check if this instance is the leader. * If it is, update the renew time, and update the entity. * If it isn't and the lease time is in the past, * set the leader, update the entity, trigger event. */ if (lease.Spec.HolderIdentity == _hostname) { _logger.LogDebug( @"The instance ""{hostname}"" is still the leader for operator ""{operator}"".", _hostname, _settings.Name); lease.Spec.RenewTime = DateTime.UtcNow; try { await _client.Update(lease); _election.LeadershipChanged(LeaderState.Leader); } catch (HttpOperationException e) when(e.Response.StatusCode == HttpStatusCode.Conflict) { _logger.LogWarning("Another instance updated the lease. Retry on next cycle."); } catch (HttpOperationException ex) { _logger.LogCritical( ex, @"A http error happened during leader election check of instance ""{hostname}"" of operator ""{operator}"". Response Message: ""{response}""", _hostname, _settings.Name, $"Phrase: {ex.Response.ReasonPhrase}\nContent: {ex.Response.Content}"); } catch (Exception ex) { _logger.LogCritical( ex, @"A generic error happened during leader election check of instance ""{hostname}"" of operator ""{operator}"".", _hostname, _settings.Name); } return; } if (lease.Spec.RenewTime.HasValue && lease.Spec.RenewTime.Value + TimeSpan.FromSeconds(lease.Spec.LeaseDurationSeconds ?? _settings.LeaderElectionLeaseDuration) < DateTime.UtcNow) { _logger.LogInformation( @"The lease for operator ""{operator}"" ran out. Electing ""{hostname}"" as leader.", _settings.Name, _hostname); lease.Spec.AcquireTime = DateTime.UtcNow; lease.Spec.RenewTime = DateTime.UtcNow; lease.Spec.HolderIdentity = _hostname; lease.Spec.LeaseTransitions ??= 0; lease.Spec.LeaseTransitions += 1; try { await _client.Update(lease); _election.LeadershipChanged(LeaderState.Leader); } catch (HttpOperationException e) when(e.Response.StatusCode == HttpStatusCode.Conflict) { _logger.LogWarning("Another instance updated the lease. Retry on next cycle."); } catch (HttpOperationException ex) { _logger.LogCritical( ex, @"A http error happened during leader election check of instance ""{hostname}"" of operator ""{operator}"". Response Message: ""{response}""", _hostname, _settings.Name, $"Phrase: {ex.Response.ReasonPhrase}\nContent: {ex.Response.Content}"); } catch (Exception ex) { _logger.LogCritical( ex, @"A generic error happened during leader election check of instance ""{hostname}"" of operator ""{operator}"".", _hostname, _settings.Name); } return; } _logger.LogDebug( @"The lease for operator ""{operator}"" did not ran out, staying/becoming candidate.", _settings.Name); _election.LeadershipChanged(LeaderState.Candidate); }