public async Task FetchLocalRepository(bool fetchExpanded) { // Casing is irrelevant for fetchers as they grab content based on file-path // which will always be lowercase. Casing IS important for the resolve flow // and is covered by tests there. string targetDtmi = "dtmi:com:example:temperaturecontroller;1"; ResolverClientOptions options = fetchExpanded ? new ResolverClientOptions(DependencyResolutionOption.TryFromExpanded) : new ResolverClientOptions(); string expectedPath = DtmiConventions.DtmiToQualifiedPath(targetDtmi, _localUri.AbsolutePath, fetchExpanded); LocalModelFetcher localFetcher = new LocalModelFetcher(_logger.Object, options); string fetcherPath = localFetcher.GetPath(targetDtmi, _localUri, fetchExpanded); Assert.AreEqual(fetcherPath, expectedPath); // Resolution correctness is covered in ResolverIntegrationTests FetchResult fetchResult = await localFetcher.FetchAsync(targetDtmi, _localUri); Assert.True(!string.IsNullOrEmpty(fetchResult.Definition)); Assert.True(!string.IsNullOrEmpty(fetchResult.Path)); Assert.AreEqual(fetchResult.FromExpanded, fetchExpanded); _logger.ValidateLog(StandardStrings.FetchingContent(fetcherPath), LogLevel.Trace, Times.Once()); }
public ModelsRepositoryMetadata FetchMetadata(Uri repositoryUri, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(FileModelFetcher)}.{nameof(FetchMetadata)}"); scope.Start(); string metadataPath = DtmiConventions.GetMetadataUri(repositoryUri).LocalPath; try { cancellationToken.ThrowIfCancellationRequested(); if (File.Exists(metadataPath)) { string content = File.ReadAllText(metadataPath, Encoding.UTF8); return(JsonSerializer.Deserialize <ModelsRepositoryMetadata>(content)); } } catch (OperationCanceledException ex) { scope.Failed(ex); throw; } catch (Exception ex) { // Exceptions thrown from fetching Repository Metadata should not be terminal. scope.Failed(ex); } ModelsRepositoryEventSource.Instance.FailureProcessingRepositoryMetadata(metadataPath); return(null); }
public static void RemoveMetadataFromLocalRepository() { string metadataFilePath = DtmiConventions.GetMetadataUri(new Uri(TestLocalModelsRepository)).LocalPath; if (File.Exists(metadataFilePath)) { File.Delete(metadataFilePath); } }
public void FetchLocalRepositoryModelDoesNotExist() { string targetDtmi = "dtmi:com:example:thermojax;1"; LocalModelFetcher localFetcher = new LocalModelFetcher(_logger.Object, new ResolverClientOptions()); Assert.ThrowsAsync <FileNotFoundException>(async() => await localFetcher.FetchAsync(targetDtmi, _localUri)); string expectedModelPath = DtmiConventions.DtmiToQualifiedPath(targetDtmi, _localUri.AbsolutePath); _logger.ValidateLog(StandardStrings.ErrorAccessLocalRepositoryModel(expectedModelPath), LogLevel.Warning, Times.Once()); }
public void GetModelInvalidDtmiDependencyThrowsException() { const string dtmi = "dtmi:com:example:invalidmodel;1"; const string invalidDep = "dtmi:azure:fakeDeviceManagement:FakeDeviceInformation;2"; string invalidDepPath = DtmiConventions.GetModelUri(invalidDep, new Uri(ModelsRepositoryTestBase.TestLocalModelsRepository)).LocalPath; string expectedExMsg = $"{string.Format(StandardStrings.GenericGetModelsError, invalidDep)} {string.Format(StandardStrings.ErrorFetchingModelContent, invalidDepPath)}"; ModelsRepositoryClient client = GetClient(ModelsRepositoryTestBase.ClientType.Local); Func <Task> act = async() => await client.GetModelAsync(dtmi); act.Should().Throw <RequestFailedException>().WithMessage(expectedExMsg); }
private static Queue <string> PrepareWork(string dtmi, Uri repositoryUri, bool tryExpanded) { Queue <string> work = new Queue <string>(); if (tryExpanded) { work.Enqueue(DtmiConventions.GetModelUri(dtmi, repositoryUri, true).AbsoluteUri); } work.Enqueue(DtmiConventions.GetModelUri(dtmi, repositoryUri, false).AbsoluteUri); return(work); }
public static async Task <int> RepoExpand(DirectoryInfo localRepo) { if (localRepo == null) { localRepo = new DirectoryInfo(Path.GetFullPath(".")); } var repoProvider = new RepoProvider(localRepo.FullName); if (!localRepo.Exists) { Outputs.WriteError($"Invalid target repository directory: {localRepo.FullName}."); return(ReturnCodes.InvalidArguments); } foreach (string file in Directory.EnumerateFiles(localRepo.FullName, "*.json", new EnumerationOptions { RecurseSubdirectories = true })) { if (file.ToLower().EndsWith(".expanded.json")) { continue; } try { var modelFile = new FileInfo(file); string dtmi = ParsingUtils.GetRootId(modelFile); if (string.IsNullOrEmpty(dtmi)) { continue; } List <string> expandedModel = await repoProvider.ExpandModel(dtmi); string formattedJson = Outputs.FormatExpandedListAsJson(expandedModel); string createPath = DtmiConventions.GetModelUri(dtmi, new Uri(localRepo.FullName), true).AbsolutePath; Outputs.WriteToFile(createPath, formattedJson); Outputs.WriteOut($"Created: {createPath}"); } catch (Exception e) { Outputs.WriteError($"Failure expanding model file: {file}, {e.Message}"); return(ReturnCodes.ProcessingError); } } return(ReturnCodes.Success); }
public static void AddMetadataToLocalRepository(bool supportsExpanded = true) { var metadata = new ModelsRepositoryMetadata(); metadata.Features.Expanded = supportsExpanded; string metadataFilePath = DtmiConventions.GetMetadataUri(new Uri(TestLocalModelsRepository)).LocalPath; var options = new JsonSerializerOptions { WriteIndented = true }; string metadataJsonString = JsonSerializer.Serialize(metadata, options); File.WriteAllText(metadataFilePath, metadataJsonString); }
public static void IsValidDtmi() { #region Snippet:ModelsRepositorySamplesDtmiConventionsIsValidDtmi // This snippet shows how to validate a given DTMI string is well-formed. // Returns true DtmiConventions.IsValidDtmi("dtmi:com:example:Thermostat;1"); // Returns false DtmiConventions.IsValidDtmi("dtmi:com:example:Thermostat"); #endregion Snippet:ModelsRepositorySamplesDtmiConventionsIsValidDtmi }
public FetchModelResult FetchModel(string dtmi, Uri repositoryUri, bool tryFromExpanded, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(FileModelFetcher)}.{nameof(FetchModel)}"); scope.Start(); try { var work = new Queue <string>(); if (tryFromExpanded) { work.Enqueue(DtmiConventions.GetModelUri(dtmi, repositoryUri, true).LocalPath); } work.Enqueue(DtmiConventions.GetModelUri(dtmi, repositoryUri, false).LocalPath); string fnfError = string.Empty; while (work.Count != 0) { cancellationToken.ThrowIfCancellationRequested(); string tryContentPath = work.Dequeue(); ModelsRepositoryEventSource.Instance.FetchingModelContent(tryContentPath); if (File.Exists(tryContentPath)) { return(new FetchModelResult { Definition = File.ReadAllText(tryContentPath, Encoding.UTF8), Path = tryContentPath }); } ModelsRepositoryEventSource.Instance.ErrorFetchingModelContent(tryContentPath); fnfError = string.Format(CultureInfo.InvariantCulture, StandardStrings.ErrorFetchingModelContent, tryContentPath); } throw new RequestFailedException( $"{string.Format(CultureInfo.InvariantCulture, StandardStrings.GenericGetModelsError, dtmi)} {fnfError}", new FileNotFoundException(fnfError)); } catch (Exception ex) { scope.Failed(ex); throw; } }
public static void Import(string modelContent, DirectoryInfo repository) { string rootId = ParsingUtils.GetRootId(modelContent); string createPath = DtmiConventions.GetModelUri(rootId, new Uri(repository.FullName)).AbsolutePath; Outputs.WriteOut($"- Importing model \"{rootId}\"..."); if (File.Exists(createPath)) { Outputs.WriteOut( $"- Skipping \"{rootId}\". Model file already exists in repository.", ConsoleColor.DarkCyan); return; } (new FileInfo(createPath)).Directory.Create(); Outputs.WriteToFile(createPath, modelContent); }
public static string EnsureValidModelFilePath(string modelFilePath, string modelContent, string repository) { if (RepoProvider.IsRelativePath(repository)) { repository = Path.GetFullPath(repository); } string rootId = ParsingUtils.GetRootId(modelContent); Uri targetModelPathUri = DtmiConventions.GetModelUri(rootId, new Uri(repository)); Uri modelFilePathUri = new Uri(modelFilePath); if (targetModelPathUri.AbsolutePath != modelFilePathUri.AbsolutePath) { return(Path.GetFullPath(targetModelPathUri.AbsolutePath)); } return(null); }
public async static Task ImportAsync(string modelContent, DirectoryInfo repository) { string rootId = new Parsing(null).GetRootId(modelContent); string createPath = DtmiConventions.DtmiToQualifiedPath(rootId, repository.FullName); Outputs.WriteOut($"- Importing model \"{rootId}\"..."); if (File.Exists(createPath)) { Outputs.WriteOut( $"Skipping \"{rootId}\". Model file already exists in repository.", ConsoleColor.DarkCyan); return; } UTF8Encoding utf8WithoutBom = new UTF8Encoding(false); (new FileInfo(createPath)).Directory.Create(); await File.WriteAllTextAsync(createPath, modelContent, utf8WithoutBom); }
// [TestCase(true)] - TODO: Uncomment when consistent remote repo available. public async Task FetchRemoteRepository(bool fetchExpanded) { string targetDtmi = "dtmi:com:example:temperaturecontroller;1"; RemoteModelFetcher remoteFetcher = new RemoteModelFetcher(_logger.Object, new ResolverClientOptions()); string expectedPath = DtmiConventions.DtmiToQualifiedPath(targetDtmi, _remoteUri.AbsoluteUri, fetchExpanded); string fetcherPath = remoteFetcher.GetPath(targetDtmi, _remoteUri, fetchExpanded); Assert.AreEqual(fetcherPath, expectedPath); // Resolution correctness is covered in ResolverIntegrationTests FetchResult fetchResult = await remoteFetcher.FetchAsync(targetDtmi, _remoteUri); Assert.True(!string.IsNullOrEmpty(fetchResult.Definition)); Assert.True(!string.IsNullOrEmpty(fetchResult.Path)); Assert.AreEqual(fetchResult.FromExpanded, fetchExpanded); _logger.ValidateLog($"{StandardStrings.FetchingContent(fetcherPath)}", LogLevel.Trace, Times.Once()); }
public void DtmiToQualifiedPath(string dtmi, string repository, string expectedPath) { if (string.IsNullOrEmpty(expectedPath)) { Action act = () => DtmiConventions.DtmiToQualifiedPath(dtmi, repository); act.Should().Throw <ArgumentException>().WithMessage(string.Format(StandardStrings.InvalidDtmiFormat, dtmi)); return; } string modelPath = DtmiConventions.DtmiToQualifiedPath(dtmi, repository); modelPath.Should().Be(expectedPath); string expectedExpandedPath = expectedPath.Replace( ModelsRepositoryConstants.JsonFileExtension, ModelsRepositoryConstants.ExpandedJsonFileExtension); string expandedModelPath = DtmiConventions.DtmiToQualifiedPath(dtmi, repository, true); expandedModelPath.Should().Be(expectedExpandedPath); }
public static string EnsureValidModelFilePath(string modelFilePath, string modelContent, string repository) { if (IsRelativePath(repository)) { repository = Path.GetFullPath(repository); } string rootId = new Parsing(null).GetRootId(modelContent); string modelPath = Path.GetFullPath(DtmiConventions.DtmiToQualifiedPath(rootId, repository)); Uri targetModelPathUri = new Uri(modelPath); Uri modelFilePathUri = new Uri(modelFilePath); if (targetModelPathUri.AbsolutePath != modelFilePathUri.AbsolutePath) { return(Path.GetFullPath(targetModelPathUri.AbsolutePath)); } return(null); }
public void DtmiToQualifiedPath(string dtmi, string expectedPath, string repository) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { repository = repository.Replace("\\", "/"); } if (string.IsNullOrEmpty(expectedPath)) { ArgumentException re = Assert.Throws<ArgumentException>(() => DtmiConventions.DtmiToQualifiedPath(dtmi, repository)); Assert.AreEqual(re.Message, StandardStrings.InvalidDtmiFormat(dtmi)); return; } string modelPath = DtmiConventions.DtmiToQualifiedPath(dtmi, repository); Assert.AreEqual($"{repository}/{expectedPath}", modelPath); string expandedModelPath = DtmiConventions.DtmiToQualifiedPath(dtmi, repository, true); Assert.AreEqual($"{repository}/{expectedPath.Replace(".json", ".expanded.json")}", expandedModelPath); }
public void GetModelUri(string dtmi, string repository, string expectedUri) { var repositoryUri = new Uri(repository); if (string.IsNullOrEmpty(expectedUri)) { Action act = () => DtmiConventions.GetModelUri(dtmi, repositoryUri); act.Should().Throw <ArgumentException>().WithMessage(string.Format(StandardStrings.InvalidDtmiFormat, dtmi)); return; } Uri modelUri = DtmiConventions.GetModelUri(dtmi, repositoryUri); modelUri.AbsoluteUri.Should().Be(expectedUri); string expectedExpandedUri = expectedUri.Replace( ModelsRepositoryConstants.JsonFileExtension, ModelsRepositoryConstants.ExpandedJsonFileExtension); Uri expandedModelUri = DtmiConventions.GetModelUri(dtmi, repositoryUri, true); expandedModelUri.Should().Be(expectedExpandedUri); }
private static FileInfo ImportModel(JsonElement modelItem, string fileName, DirectoryInfo repository, ILogger logger) { //Do DTMI verification var rootId = Validations.GetRootId(modelItem, fileName); if (!ResolverClient.IsValidDtmi(rootId.GetString())) { throw new InvalidDTMIException(rootId); } if (!Validations.ValidateDTMIs(modelItem, fileName, logger)) { throw new InvalidDTMIException(fileName); } // write file to repository location var newPath = DtmiConventions.DtmiToQualifiedPath(rootId.GetString(), repository.FullName); // TODO: consistent paths. Use global arg formatters. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { newPath = newPath.Replace("\\", "/"); } if (!File.Exists(newPath)) { CheckCreateDirectory(newPath); logger.LogTrace($"Writing new file to '{newPath}'. "); File.WriteAllText(newPath, modelItem.ToString(), Encoding.UTF8); } else { throw new IOException($"File '{newPath}' already exists. Please remove prior to execution."); } //return file info return(new FileInfo(newPath)); }
public static void GetModelUri() { #region Snippet:ModelsRepositorySamplesDtmiConventionsGetModelUri // This snippet shows obtaining a fully qualified path to a model file. // Local repository example Uri localRepositoryUri = new Uri("file:///path/to/repository/"); string fullyQualifiedModelPath = DtmiConventions.GetModelUri("dtmi:com:example:Thermostat;1", localRepositoryUri).AbsolutePath; // Prints '/path/to/repository/dtmi/com/example/thermostat-1.json' Console.WriteLine(fullyQualifiedModelPath); // Remote repository example Uri remoteRepositoryUri = new Uri("https://contoso.com/models/"); fullyQualifiedModelPath = DtmiConventions.GetModelUri("dtmi:com:example:Thermostat;1", remoteRepositoryUri).AbsoluteUri; // Prints 'https://contoso.com/models/dtmi/com/example/thermostat-1.json' Console.WriteLine(fullyQualifiedModelPath); #endregion Snippet:ModelsRepositorySamplesDtmiConventionsGetModelUri }
public static void GetDtmiToQualifiedPath() { #region Snippet:ModelsRepositorySamplesDtmiConventionsGetDtmiToQualifiedPath // This snippet shows obtaining a fully qualified path to a model file. // Local repository example string localRepository = "/path/to/repository"; string fullyQualifiedModelPath = DtmiConventions.DtmiToQualifiedPath("dtmi:com:example:Thermostat;1", localRepository); // Prints '/path/to/repository/dtmi/com/example/thermostat-1.json' Console.WriteLine(fullyQualifiedModelPath); // Remote repository example string remoteRepository = "https://contoso.com/models"; fullyQualifiedModelPath = DtmiConventions.DtmiToQualifiedPath("dtmi:com:example:Thermostat;1", remoteRepository); // Prints 'https://contoso.com/models/dtmi/com/example/thermostat-1.json' Console.WriteLine(fullyQualifiedModelPath); #endregion Snippet:ModelsRepositorySamplesDtmiConventionsGetDtmiToQualifiedPath }
public void DtmiToQualifiedPath(string dtmi, string expectedPath, string repository) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { repository = repository.Replace("\\", "/"); } if (string.IsNullOrEmpty(expectedPath)) { Action act = () => DtmiConventions.DtmiToQualifiedPath(dtmi, repository); act.Should().Throw <ArgumentException>().WithMessage(string.Format(StandardStrings.InvalidDtmiFormat, dtmi)); return; } string modelPath = DtmiConventions.DtmiToQualifiedPath(dtmi, repository); modelPath.Should().Be($"{repository}/{expectedPath}"); string expandedModelPath = DtmiConventions.DtmiToQualifiedPath(dtmi, repository, true); expandedModelPath .Should() .Be($"{repository}/{expectedPath.Replace(ModelsRepositoryConstants.JsonFileExtension, ModelsRepositoryConstants.ExpandedJsonFileExtension)}"); }
private static string GetPath(string dtmi, Uri repositoryUri, bool expanded = false) { string registryPath = repositoryUri.AbsolutePath; return(DtmiConventions.DtmiToQualifiedPath(dtmi, registryPath, expanded)); }
public void GetMetadataUri(string repository, string expectedUri) { Uri metadataUri = DtmiConventions.GetMetadataUri(new Uri(repository)); metadataUri.AbsoluteUri.Should().Be(expectedUri); }
public void IsValidDtmi(string dtmi, bool expected) { DtmiConventions.IsValidDtmi(dtmi).Should().Be(expected); }
public void DtmiToPath(string dtmi, string expectedPath) { DtmiConventions.DtmiToPath(dtmi).Should().Be(expectedPath); }
public void DtmiToPath(string dtmi, string expectedPath) { Assert.AreEqual(expectedPath, DtmiConventions.DtmiToPath(dtmi)); }
private static string GetPath(string dtmi, Uri repositoryUri, bool expanded = false) { string absoluteUri = repositoryUri.AbsoluteUri; return(DtmiConventions.DtmiToQualifiedPath(dtmi, absoluteUri, expanded)); }