private async Task <IDictionary <string, string> > ResolveEnvironmentPreview(EnvironmentPreview environment) { // if there is a reference to an existing Environment, retrieve its keys if (!string.IsNullOrWhiteSpace(environment.Category) && !string.IsNullOrWhiteSpace(environment.Name)) { var id = new EnvironmentIdentifier(environment.Category, environment.Name); var result = await _store.Environments.GetKeys(new EnvironmentKeyQueryParameters { Environment = id, Range = QueryRange.All }); if (!result.IsError) { return(result.Data); } Logger.LogWarning($"could not retrieve referenced environment '{id}' for preview: {result.Message}"); } // if no reference or couldn't retrieve keys - fall back to custom-keys return(environment.Keys ?? new Dictionary <string, string>()); }
/// <inheritdoc /> public ConfigEnvironment(EnvironmentIdentifier identifier) { if (identifier is null) { throw new ArgumentNullException(nameof(identifier)); } if (string.IsNullOrWhiteSpace(identifier.Category)) { throw new ArgumentNullException(nameof(identifier), $"{nameof(identifier.Category)} is null or empty"); } if (string.IsNullOrWhiteSpace(identifier.Name)) { throw new ArgumentNullException(nameof(identifier), $"{nameof(identifier.Name)} is null or empty"); } Created = false; Deleted = false; Identifier = new EnvironmentIdentifier(identifier.Category, identifier.Name); IsDefault = false; Keys = new Dictionary <string, ConfigEnvironmentKey>(StringComparer.OrdinalIgnoreCase); }
public async Task <IActionResult> GetVersion([FromRoute] string environmentCategory, [FromRoute] string environmentName, [FromRoute] string structureName, [FromRoute] int structureVersion, [FromQuery] DateTime when) { try { var envIdentifier = new EnvironmentIdentifier(environmentCategory, environmentName); var structureIdentifier = new StructureIdentifier(structureName, structureVersion); var configId = new ConfigurationIdentifier(envIdentifier, structureIdentifier, default); var version = await _store.Configurations.GetVersion(configId, when); if (version.IsError) { return(ProviderError(version)); } // add version to the response-headers Response.Headers.Add("x-version", version.Data); return(Result(version)); } catch (Exception e) { KnownMetrics.Exception.WithLabels(e.GetType().Name).Inc(); Logger.LogError(e, "failed to add new environment at (" + $"{nameof(environmentCategory)}: {environmentCategory}; " + $"{nameof(environmentName)}: {environmentName}; " + $"{nameof(structureName)}: {structureName}; " + $"{nameof(structureVersion)}: {structureVersion}; " + $"{nameof(when)}: {when})"); return(StatusCode(HttpStatusCode.InternalServerError, "failed to retrieve configuration-version")); } }
public async Task <IActionResult> GetUsedKeysPerStructureAll([FromRoute] string environmentCategory, [FromRoute] string environmentName) { if (string.IsNullOrWhiteSpace(environmentCategory)) { return(BadRequest("no environment-category given")); } if (string.IsNullOrWhiteSpace(environmentName)) { return(BadRequest("no environment-name given")); } var envId = new EnvironmentIdentifier(environmentCategory, environmentName); var envKeyResult = await _store.Environments.GetKeys(new EnvironmentKeyQueryParameters { Environment = envId, Range = QueryRange.All }); if (envKeyResult.IsError) { return(ProviderError(envKeyResult)); } var envKeys = envKeyResult.Data; var configResult = await _store.Configurations.GetAvailableWithEnvironment(envId, DateTime.MinValue, QueryRange.All); if (configResult.IsError) { return(ProviderError(configResult)); } return(Result(await AnnotateEnvironmentKeys(envKeys, configResult.Data))); }
/// <summary> /// extract the actual desired environment out of the Environment-Export /// </summary> /// <param name="export"></param> /// <returns></returns> private EnvironmentExport GetExportedEnvironment(ConfigExport export) { if (export.Environments.Length > 1) { if (string.IsNullOrWhiteSpace(UseInputEnvironment)) { Output.WriteError("multiple Environments defined in given export, but no '-u|--use-environment' parameter given"); return(null); } var useSplit = UseInputEnvironment.Split('/'); var usedEnvironmentId = new EnvironmentIdentifier(useSplit[0], useSplit[1]); return(export.Environments .FirstOrDefault(e => string.Equals(e.Category, usedEnvironmentId.Category, StringComparison.OrdinalIgnoreCase) && string.Equals(e.Name, usedEnvironmentId.Name, StringComparison.OrdinalIgnoreCase))); } return(export.Environments.FirstOrDefault()); }
/// <inheritdoc /> public EnvironmentKeysModified(EnvironmentIdentifier identifier, ConfigKeyAction[] modifiedKeys) { Identifier = identifier; ModifiedKeys = modifiedKeys; }
/// <inheritdoc /> public DefaultEnvironmentCreated(EnvironmentIdentifier identifier) { Identifier = identifier; }
public async Task <IActionResult> InspectUploadedStructure([FromRoute] string environmentCategory, [FromRoute] string environmentName, [FromBody] DtoStructure structure) { if (string.IsNullOrWhiteSpace(environmentCategory)) { return(BadRequest("no environment-category given")); } if (string.IsNullOrWhiteSpace(environmentName)) { return(BadRequest("no environment-name given")); } if (structure is null) { return(BadRequest("no structure was uploaded")); } switch (structure.Structure.ValueKind) { case JsonValueKind.Object: if (!structure.Structure.EnumerateObject().Any()) { return(BadRequest("empty structure-body given")); } break; case JsonValueKind.Array: if (!structure.Structure.EnumerateArray().Any()) { return(BadRequest("empty structure-body given")); } break; default: return(BadRequest("invalid structure-body given (invalid type or null)")); } IDictionary <string, string> structKeys; try { structKeys = _translator.ToDictionary(structure.Structure); } catch (Exception e) { Logger.LogWarning(e, "could not translate given json.Structure to dictionary"); return(BadRequest("structure could not be mapped to a dictionary ($.Structure)")); } var envId = new EnvironmentIdentifier(environmentCategory, environmentName); var envKeysResult = await _store.Environments.GetKeys(new EnvironmentKeyQueryParameters { Environment = envId, Range = QueryRange.All }); if (envKeysResult.IsError) { return(ProviderError(envKeysResult)); } var envKeys = envKeysResult.Data; CompilationResult compilationResult; try { compilationResult = _compiler.Compile( new EnvironmentCompilationInfo { Keys = envKeys, Name = envId.ToString() }, new StructureCompilationInfo { Name = structure.Name ?? "Inspected Structure", Keys = structKeys, Variables = (structure.Variables ?? new Dictionary <string, object>()).ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString()) }, _parser); } catch (Exception e) { Logger.LogWarning(e, $"structure could not be inspected in context of '{envId}'; compilation failed"); return(Ok(new StructureInspectionResult { CompilationSuccessful = false })); } var result = AnalyzeCompilation(compilationResult); return(Ok(result)); }
public async Task <IActionResult> InspectStructure([FromRoute] string environmentCategory, [FromRoute] string environmentName, [FromRoute] string structureName, [FromRoute] int structureVersion) { if (string.IsNullOrWhiteSpace(environmentCategory)) { return(BadRequest("no environment-category given")); } if (string.IsNullOrWhiteSpace(environmentName)) { return(BadRequest("no environment-name given")); } if (string.IsNullOrWhiteSpace(structureName)) { return(BadRequest("no structure-name was given")); } if (structureVersion <= 0) { return(BadRequest("structure-version invalid")); } var envId = new EnvironmentIdentifier(environmentCategory, environmentName); var structId = new StructureIdentifier(structureName, structureVersion); var envKeysResult = await _store.Environments.GetKeys(new EnvironmentKeyQueryParameters { Environment = envId, Range = QueryRange.All }); if (envKeysResult.IsError) { return(ProviderError(envKeysResult)); } var envKeys = envKeysResult.Data; IDictionary <string, string> structKeys; IDictionary <string, string> structVars; try { var keyResult = await _store.Structures.GetKeys(structId, QueryRange.All); if (keyResult.IsError) { return(ProviderError(keyResult)); } var varResult = await _store.Structures.GetVariables(structId, QueryRange.All); if (varResult.IsError) { return(ProviderError(varResult)); } structKeys = keyResult.Data; structVars = varResult.Data; } catch (Exception e) { Logger.LogWarning(e, "could not retrieve structure-data or -variables"); return(BadRequest("could not retrieve structure-data or -variables")); } CompilationResult compilationResult; try { compilationResult = _compiler.Compile( new EnvironmentCompilationInfo { Keys = envKeys, Name = envId.ToString() }, new StructureCompilationInfo { Name = structureName, Keys = structKeys, Variables = structVars }, _parser); } catch (Exception e) { Logger.LogWarning(e, $"structure could not be inspected in context of '{envId}'; compilation failed"); return(Ok(new StructureInspectionResult { CompilationSuccessful = false })); } var result = AnalyzeCompilation(compilationResult); return(Ok(result)); }
public async Task <IActionResult> PreviewConfiguration([FromRoute] string environmentCategory, [FromRoute] string environmentName, [FromRoute] string structureName, [FromRoute] int structureVersion) { var envId = new EnvironmentIdentifier(environmentCategory, environmentName); var structId = new StructureIdentifier(structureName, structureVersion); var structureKeyResult = await _store.Structures.GetKeys(structId, QueryRange.All); if (structureKeyResult.IsError) { return(ProviderError(structureKeyResult)); } var structureVariableResult = await _store.Structures.GetVariables(structId, QueryRange.All); if (structureVariableResult.IsError) { return(ProviderError(structureVariableResult)); } var environmentResult = await _store.Environments.GetKeys(new EnvironmentKeyQueryParameters { Environment = envId, Range = QueryRange.All }); if (environmentResult.IsError) { return(ProviderError(environmentResult)); } var structureSnapshot = structureKeyResult.Data; var variableSnapshot = structureVariableResult.Data; var environmentSnapshot = environmentResult.Data; var environmentInfo = new EnvironmentCompilationInfo { Name = $"{envId.Category}/{envId.Name}", Keys = environmentSnapshot }; var structureInfo = new StructureCompilationInfo { Name = $"{structId.Name}/{structId.Version}", Keys = structureSnapshot, Variables = variableSnapshot }; try { var compiled = _compiler.Compile(environmentInfo, structureInfo, _parser); var json = _translator.ToJson(compiled.CompiledConfiguration); return(Ok(json)); } catch (Exception e) { KnownMetrics.Exception.WithLabels(e.GetType().Name).Inc(); Logger.LogError(e, "failed to add new environment at (" + $"{nameof(environmentCategory)}: {environmentCategory}; " + $"{nameof(environmentName)}: {environmentName}; " + $"{nameof(structureName)}: {structureName}; " + $"{nameof(structureVersion)}: {structureVersion})"); return(Ok(JsonDocument.Parse("{}").RootElement)); } }
/// <inheritdoc /> public ConfigurationIdentifier(EnvironmentIdentifier environment, StructureIdentifier structure, long version) { Environment = environment; Structure = structure; Version = version; }
/// <inheritdoc /> public async Task <IResult <IList <DtoConfigKeyCompletion> > > GetKeyAutoComplete(EnvironmentIdentifier identifier, string key, QueryRange range, long version) { try { _logger.LogDebug($"attempting to retrieve next paths in '{identifier}' for path '{key}', range={range}"); _logger.LogDebug($"removing escape-sequences from key"); key = Uri.UnescapeDataString(key ?? string.Empty); _logger.LogDebug($"using new key='{key}'"); var envResult = await(version <= 0 ? _domainObjectStore.ReplayObject(new ConfigEnvironment(identifier), identifier.ToString()) : _domainObjectStore.ReplayObject(new ConfigEnvironment(identifier), identifier.ToString(), version)); if (envResult.IsError) { return(Result.Error <IList <DtoConfigKeyCompletion> >( "no environment found with (" + $"{nameof(identifier.Category)}: {identifier.Category}; " + $"{nameof(identifier.Name)}: {identifier.Name})", ErrorCode.NotFound)); } var environment = envResult.Data; var paths = environment.KeyPaths; // send auto-completion data for all roots if (string.IsNullOrWhiteSpace(key)) { _logger.LogDebug("early-exit, sending root-paths because key was empty"); return(Result.Success <IList <DtoConfigKeyCompletion> >( paths.Select(p => new DtoConfigKeyCompletion { HasChildren = p.Children.Any(), FullPath = p.FullPath, Completion = p.Path }) .OrderBy(p => p.Completion) .ToList())); } var parts = new Queue <string>(key.Contains('/') ? key.Split('/') : new[] { key }); var rootPart = parts.Dequeue(); _logger.LogDebug($"starting with path '{rootPart}'"); // if the user is searching within the roots if (!parts.Any()) { _logger.LogDebug($"no further parts found, returning direct children"); var possibleRoots = paths.Where(p => p.Path.Contains(rootPart)) .ToList(); // if there is only one possible root, and that one matches what were searching for // we're returning all paths directly below that one List <ConfigEnvironmentKeyPath> selectedRoots; if (possibleRoots.Count == 1 && possibleRoots.First() .Path .Equals(rootPart, StringComparison.OrdinalIgnoreCase)) { _logger.LogDebug("selecting children of only root for further processing"); selectedRoots = paths.First().Children; } else { _logger.LogDebug("selecting original matches for further processing"); selectedRoots = paths; } return(Result.Success <IList <DtoConfigKeyCompletion> >( selectedRoots.Select(p => new DtoConfigKeyCompletion { HasChildren = p.Children.Any(), FullPath = p.Children.Any() ? p.FullPath + '/' : p.FullPath, Completion = p.Path }) .OrderBy(p => p.Completion) .ToList())); } var root = paths.FirstOrDefault(p => p.Path == rootPart); if (root is null) { _logger.LogDebug($"no path found that matches '{rootPart}'"); return(Result.Error <IList <DtoConfigKeyCompletion> >( $"key '{key}' is ambiguous, root does not match anything", ErrorCode.NotFound)); } var result = GetKeyAutoCompleteInternal(root, parts.ToList(), range); return(result); } catch (Exception e) { _logger.LogError(e, $"failed to get autocomplete data for '{key}' in " + $"({nameof(identifier.Category)}: {identifier.Category}; {nameof(identifier.Name)}: {identifier.Name})"); return(Result.Error <IList <DtoConfigKeyCompletion> >($"failed to get autocomplete data for '{key}' in " + $"({nameof(identifier.Category)}: {identifier.Category}; {nameof(identifier.Name)}: {identifier.Name}): {e}", ErrorCode.DbQueryError)); } }
/// <inheritdoc /> public Task <IResult <IList <DtoConfigKeyCompletion> > > GetKeyAutoComplete(EnvironmentIdentifier identifier, string key, QueryRange range) => GetKeyAutoComplete(identifier, key, range, long.MaxValue);
/// <inheritdoc /> public async Task <IResult <IList <ConfigurationIdentifier> > > GetAvailableWithEnvironment(EnvironmentIdentifier environment, DateTime when, QueryRange range) { try { _logger.LogDebug($"collecting available configurations at '{when:O}', range={range}"); var list = await _domainObjectStore.ReplayObject <PreparedConfigurationList>(); if (list.IsError) { return(Result.Success <IList <ConfigurationIdentifier> >(new List <ConfigurationIdentifier>())); } var utcWhen = when.ToUniversalTime(); _logger.LogDebug($"using utc-time={utcWhen:O}"); var identifiers = list.Data .GetIdentifiers() .Where(pair => (pair.Value.ValidFrom ?? DateTime.MinValue) <= utcWhen && (pair.Value.ValidTo ?? DateTime.MaxValue) >= utcWhen) .Where(pair => pair.Key.Environment.Category == environment.Category && pair.Key.Environment.Name == environment.Name) .OrderBy(pair => pair.Key.Environment.Category) .ThenBy(pair => pair.Key.Environment.Name) .ThenBy(pair => pair.Key.Structure.Name) .ThenByDescending(s => s.Key.Structure.Version) .Skip(range.Offset) .Take(range.Length) .Select(pair => pair.Key) .ToList(); _logger.LogDebug($"collected '{identifiers.Count}' identifiers"); return(Result.Success <IList <ConfigurationIdentifier> >(identifiers)); } catch (Exception e) { _logger.LogError(e, "failed to retrieve projected configurations"); return(Result.Error <IList <ConfigurationIdentifier> >("failed to retrieve projected configurations", ErrorCode.DbQueryError)); } }
/// <inheritdoc /> public EnvironmentDeleted(EnvironmentIdentifier identifier) { Identifier = identifier; }