diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java index 5a49487c5b98c..06e62c6bb16e7 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/DtmiConventions.java @@ -41,7 +41,6 @@ public static boolean isValidDtmi(String dtmi) { if (dtmi == null || dtmi.isEmpty()) { return false; } - return VALID_DTMI_PATTERN.matcher(dtmi).matches(); } @@ -74,6 +73,44 @@ public static URI getModelUri(String dtmi, URI repositoryUri, boolean expanded) } } + /** + * Generates the model path. + * + * @param dtmi DigitalTwin Model Id. + * @param expanded Is model from precomputed values + * @return The model path. + */ + public static String getModelPath(String dtmi, boolean expanded) { + String dtmiPath = dtmiToPath(dtmi); + + if (expanded) { + dtmiPath = dtmiPath.replace(ModelsRepositoryConstants.JSON_EXTENSION, + ModelsRepositoryConstants.JSON_EXPANDED_EXTENSION); + } + + return dtmiPath; + } + + /** + * Generates the model repository's metadata URI. + * + * @param repositoryUri The repository uri + * @return The repository metadata uri. + * @throws IllegalArgumentException if the provided repository URI is not valid + */ + public static URI getMetadataUri(URI repositoryUri) { + try { + String stringUri = repositoryUri.toString(); + if (stringUri.endsWith("/")) { + return new URI(stringUri + ModelsRepositoryConstants.MODELS_REPOSITORY_METADATA_FILE); + } else { + return new URI(stringUri + "/" + ModelsRepositoryConstants.MODELS_REPOSITORY_METADATA_FILE); + } + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Invalid uri syntax"); + } + } + static String dtmiToPath(String dtmi) { if (!isValidDtmi(dtmi)) { throw new IllegalArgumentException(String.format(StatusStrings.INVALID_DTMI_FORMAT_S, dtmi)); diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java index db28c05aa825d..af2b54c92113d 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelDependencyResolution.java @@ -13,13 +13,7 @@ public enum ModelDependencyResolution { DISABLED, /** - * Enable model dependency resolution. The client will parse models and calculate dependencies recursively. + * Enable model dependency resolution. */ ENABLED, - - /** - * Try to get pre-computed model dependencies using .expanded.json. - * If the model expanded form does not exist, it will fall back to {@link ModelDependencyResolution#ENABLED}. - */ - TRY_FROM_EXPANDED, } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java index e82b0e913e793..cb949207186c6 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/ModelsRepositoryClientBuilder.java @@ -58,7 +58,7 @@ public final class ModelsRepositoryClientBuilder { // Fields with default values. private URI repositoryEndpoint; - private ModelDependencyResolution modelDependencyResolution = ModelDependencyResolution.TRY_FROM_EXPANDED; + private ModelDependencyResolution modelDependencyResolution = ModelDependencyResolution.ENABLED; // optional/have default values private ModelsRepositoryServiceVersion serviceVersion; @@ -152,7 +152,7 @@ private static HttpPipeline constructPipeline( /** * Create a {@link ModelsRepositoryClient} based on the builder settings. * - * @return the created synchronous ModelsRepotioryClient + * @return the created synchronous ModelsRepositoryClient */ public ModelsRepositoryClient buildClient() { return new ModelsRepositoryClient(buildAsyncClient()); diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java index a8182568421d6..1361a0413eb43 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/FileModelFetcher.java @@ -7,8 +7,8 @@ import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; import com.azure.iot.modelsrepository.DtmiConventions; -import com.azure.iot.modelsrepository.ModelDependencyResolution; -import com.azure.iot.modelsrepository.implementation.models.FetchResult; +import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult; +import com.azure.iot.modelsrepository.implementation.models.FetchModelResult; import reactor.core.publisher.Mono; import java.io.File; @@ -39,15 +39,15 @@ class FileModelFetcher implements ModelFetcher { } @Override - public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDependencyResolution resolutionOption, Context context) { + public Mono fetchModelAsync(String dtmi, URI repositoryUri, boolean tryFromExpanded, Context context) { return Mono.defer(() -> { Queue work = new LinkedList<>(); try { - if (resolutionOption == ModelDependencyResolution.TRY_FROM_EXPANDED) { - work.add(getPath(dtmi, repositoryUri, true)); + if (tryFromExpanded) { + work.add(getModelPath(dtmi, repositoryUri, true)); } - work.add(getPath(dtmi, repositoryUri, false)); + work.add(getModelPath(dtmi, repositoryUri, false)); } catch (MalformedURLException | URISyntaxException e) { return Mono.error(new AzureException(e)); } @@ -63,7 +63,7 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende if (Files.exists(path)) { try { return Mono.just( - new FetchResult() + new FetchModelResult() .setDefinition(new String(Files.readAllBytes(path), StandardCharsets.UTF_8)) .setPath(tryContentPath)); } catch (IOException e) { @@ -80,8 +80,41 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende }); } - private String getPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException, MalformedURLException { + @Override + public Mono fetchMetadataAsync(URI repositoryUri, Context context) { + try { + String tryContentPath = getMetadataPath(repositoryUri); + Path path = Paths.get(new File(tryContentPath).getPath()); + + logger.info(StatusStrings.FETCHING_METADATA_CONTENT, path); + + if (Files.exists(path)) { + try { + return Mono.just( + new FetchMetadataResult() + .setDefinition(new String(Files.readAllBytes(path), StandardCharsets.UTF_8)) + .setPath(tryContentPath)); + } catch (IOException e) { + logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s.", + path.toString(), e.getMessage())); + return Mono.error(new AzureException(e)); + } + } + + logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, path.toString())); + return Mono.just(new FetchMetadataResult()); + } catch (MalformedURLException | URISyntaxException e) { + return Mono.error(new AzureException(e)); + } + } + + private String getModelPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException, MalformedURLException { return DtmiConventions.getModelUri(dtmi, repositoryUri, expanded) .getPath(); } + + private String getMetadataPath(URI repositoryUri) throws URISyntaxException, MalformedURLException { + return DtmiConventions.getMetadataUri(repositoryUri) + .getPath(); + } } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java index 6a36fd9cacf84..f5773f3cef9c9 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/HttpModelFetcher.java @@ -7,10 +7,12 @@ import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; import com.azure.iot.modelsrepository.DtmiConventions; -import com.azure.iot.modelsrepository.ModelDependencyResolution; -import com.azure.iot.modelsrepository.implementation.models.FetchResult; +import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult; +import com.azure.iot.modelsrepository.implementation.models.FetchModelResult; +import com.fasterxml.jackson.core.JsonProcessingException; import reactor.core.publisher.Mono; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -31,14 +33,14 @@ class HttpModelFetcher implements ModelFetcher { } @Override - public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDependencyResolution resolutionOption, Context context) { + public Mono fetchModelAsync(String dtmi, URI repositoryUri, boolean tryFromExpanded, Context context) { return Mono.defer(() -> { Queue work = new LinkedList<>(); try { - if (resolutionOption == ModelDependencyResolution.TRY_FROM_EXPANDED) { - work.add(getPath(dtmi, repositoryUri, true)); + if (tryFromExpanded) { + work.add(getModelPath(dtmi, repositoryUri, true)); } - work.add(getPath(dtmi, repositoryUri, false)); + work.add(getModelPath(dtmi, repositoryUri, false)); } catch (Exception e) { return Mono.error(new AzureException(e)); } @@ -52,13 +54,40 @@ public Mono fetchAsync(String dtmi, URI repositoryUri, ModelDepende if (work.size() != 0) { return evaluatePath(work.poll(), context); } else { + logger.error(String.format(StatusStrings.ERROR_FETCHING_MODEL_CONTENT, tryContentPath)); return Mono.error(error); } }) - .map(s -> new FetchResult().setPath(tryContentPath).setDefinition(s)); + .map(s -> new FetchModelResult().setPath(tryContentPath).setDefinition(s)); }); } + @Override + public Mono fetchMetadataAsync(URI repositoryUri, Context context) { + try { + String tryContentPath = getMetadataPath(repositoryUri); + + logger.info(StatusStrings.FETCHING_METADATA_CONTENT, tryContentPath); + + return evaluatePath(tryContentPath, context) + .onErrorResume(error -> { + logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT + " Error: %s", + tryContentPath, error.getMessage())); + return Mono.error(error); + }) + .map(s -> { + try { + return new FetchMetadataResult().setPath(tryContentPath).setDefinition(s); + } catch (JsonProcessingException e) { + logger.error(String.format(StatusStrings.ERROR_FETCHING_METADATA_CONTENT, tryContentPath)); + return null; + } + }); + } catch (MalformedURLException | URISyntaxException e) { + return Mono.error(new AzureException(e)); + } + } + private Mono evaluatePath(String tryContentPath, Context context) { return protocolLayer .getModelsRepository() @@ -69,7 +98,11 @@ private Mono evaluatePath(String tryContentPath, Context context) { }); } - private String getPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException { - return DtmiConventions.getModelUri(dtmi, repositoryUri, expanded).getPath(); + private String getModelPath(String dtmi, URI repositoryUri, boolean expanded) throws URISyntaxException { + return DtmiConventions.getModelPath(dtmi, expanded); + } + + private String getMetadataPath(URI repositoryUri) throws URISyntaxException, MalformedURLException { + return DtmiConventions.getMetadataUri(repositoryUri).getPath(); } } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchResult.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchModelResult.java similarity index 62% rename from sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchResult.java rename to sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchModelResult.java index 2b11e3193d977..579d059b7b4b2 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchResult.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/IntermediateFetchModelResult.java @@ -3,7 +3,7 @@ package com.azure.iot.modelsrepository.implementation; -import com.azure.iot.modelsrepository.implementation.models.FetchResult; +import com.azure.iot.modelsrepository.implementation.models.FetchModelResult; import java.util.Map; @@ -11,17 +11,17 @@ * This type is used to unify the expand operation return types in the recursive function and has no other use cases. * Do not take any dependencies on this type. */ -class IntermediateFetchResult { - private final FetchResult fetchResult; +class IntermediateFetchModelResult { + private final FetchModelResult fetchModelResult; private final Map map; - IntermediateFetchResult(FetchResult fetchResult, Map map) { - this.fetchResult = fetchResult; + IntermediateFetchModelResult(FetchModelResult fetchModelResult, Map map) { + this.fetchModelResult = fetchModelResult; this.map = map; } - public FetchResult getFetchResult() { - return fetchResult; + public FetchModelResult getFetchModelResult() { + return fetchModelResult; } public Map getMap() { diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java index 1de022101406f..2c9a49bbcee50 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelFetcher.java @@ -4,12 +4,13 @@ package com.azure.iot.modelsrepository.implementation; import com.azure.core.util.Context; -import com.azure.iot.modelsrepository.ModelDependencyResolution; -import com.azure.iot.modelsrepository.implementation.models.FetchResult; +import com.azure.iot.modelsrepository.implementation.models.FetchMetadataResult; +import com.azure.iot.modelsrepository.implementation.models.FetchModelResult; import reactor.core.publisher.Mono; import java.net.URI; interface ModelFetcher { - Mono fetchAsync(String dtmi, URI repositoryUri, ModelDependencyResolution resolutionOption, Context context); + Mono fetchModelAsync(String dtmi, URI repositoryUri, boolean tryFromExpanded, Context context); + Mono fetchMetadataAsync(URI repositoryUri, Context context); } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java index f02a265adfa4e..d1efc6044f432 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/ModelsRepositoryConstants.java @@ -9,6 +9,7 @@ public class ModelsRepositoryConstants { public static final String JSON_EXTENSION = ".json"; public static final String JSON_EXPANDED_EXTENSION = ".expanded.json"; public static final String DEFAULT_MODELS_REPOSITORY_ENDPOINT = "https://devicemodels.azure.com"; + public static final String MODELS_REPOSITORY_METADATA_FILE = "metadata.json"; // DTDL conventions public static final String DTDL_TYPE = "@type"; diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java index 7eb2e6dabd618..b713b58afbc83 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/RepositoryHandler.java @@ -3,26 +3,31 @@ package com.azure.iot.modelsrepository.implementation; -import com.azure.core.exception.AzureException; import com.azure.core.util.Context; +import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.logging.LogLevel; import com.azure.iot.modelsrepository.DtmiConventions; import com.azure.iot.modelsrepository.ModelDependencyResolution; -import com.azure.iot.modelsrepository.implementation.models.FetchResult; +import com.azure.iot.modelsrepository.implementation.models.FetchModelResult; import com.azure.iot.modelsrepository.implementation.models.ModelMetadata; +import com.fasterxml.jackson.core.JsonProcessingException; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.URI; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Map; -import java.util.Queue; import java.util.List; -import java.util.LinkedList; import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; - +/** + * The {@link RepositoryHandler} is responsible for processing fetched models + * and generates processed results which are sent back to the client. + */ public final class RepositoryHandler { private final URI repositoryUri; @@ -35,8 +40,8 @@ public RepositoryHandler(URI repositoryUri, ModelsRepositoryAPIImpl protocolLaye if (this.repositoryUri.getScheme() != null && this.repositoryUri.getScheme() - .toLowerCase(Locale.getDefault()) - .startsWith(ModelsRepositoryConstants.HTTP)) { + .toLowerCase(Locale.getDefault()) + .startsWith(ModelsRepositoryConstants.HTTP)) { this.modelFetcher = new HttpModelFetcher(protocolLayer); } else { this.modelFetcher = new FileModelFetcher(); @@ -47,87 +52,75 @@ public Mono> processAsync(String dtmi, ModelDependencyResolu return processAsync(Collections.singletonList(dtmi), resolutionOptions, context); } - public Mono> processAsync(Iterable dtmis, ModelDependencyResolution - resolutionOptions, Context context) { - - Map processedModels = new HashMap<>(); - Queue modelsToProcess = prepareWork(dtmis); - - return processAsync(modelsToProcess, resolutionOptions, context, processedModels) - .last() - .map(IntermediateFetchResult::getMap); - } - - private Flux processAsync( - Queue remainingWork, - ModelDependencyResolution resolutionOption, - Context context, - Map currentResults) { - - if (remainingWork.isEmpty()) { - return Flux.empty(); - } - - String targetDtmi = remainingWork.poll(); + public Mono> processAsync(Iterable dtmis, ModelDependencyResolution resolutionOptions, Context context) { + List modelsToProcess = prepareWork(dtmis); - logger.info(String.format(StatusStrings.PROCESSING_DTMIS, targetDtmi)); + return isExpandedAvailable(resolutionOptions, context) + .flatMapMany(tryExpanded -> processAsync(tryExpanded, modelsToProcess, resolutionOptions, context)) + .collectList() + .flatMap(results -> { + Map processedModels = new HashMap<>(); - return modelFetcher.fetchAsync(targetDtmi, repositoryUri, resolutionOption, context) - .map(result -> new IntermediateFetchResult(result, currentResults)) - .expand(customType -> { - Map results = customType.getMap(); - FetchResult response = customType.getFetchResult(); - - if (response.isFromExpanded()) { - try { - Map expanded = new ModelsQuery(response.getDefinition()).listToMap(); - for (Map.Entry item : expanded.entrySet()) { - if (!results.containsKey(item.getKey())) { - results.put(item.getKey(), item.getValue()); + try { + for (FetchModelResult result : results) { + ModelsQuery modelsQuery = new ModelsQuery(result.getDefinition()); + if (result.isFromExpanded()) { + Map expanded = modelsQuery.listToMap(); + for (Map.Entry item : expanded.entrySet()) { + processedModels.putIfAbsent(item.getKey(), item.getValue()); } + } else { + ModelMetadata metadata = modelsQuery.parseModel(); + processedModels.put(metadata.getId(), result.getDefinition()); } - - return processAsync(remainingWork, resolutionOption, context, results); - } catch (Exception e) { - return Mono.error(e); } + } catch (JsonProcessingException ex) { + return Mono.error(ex); } - try { - ModelMetadata metadata = new ModelsQuery(response.getDefinition()).parseModel(); + return Mono.just(processedModels); + }); + } - if (resolutionOption == ModelDependencyResolution.ENABLED || resolutionOption == ModelDependencyResolution.TRY_FROM_EXPANDED) { - List dependencies = metadata.getDependencies(); + private Flux processAsync(boolean tryExpanded, List dtmis, ModelDependencyResolution resolution, Context context) { + return Flux.concat(dtmis.stream().map(dtmi -> processDtmi(tryExpanded, dtmi, resolution, context)) + .collect(Collectors.toList())); + } - if (dependencies.size() > 0) { - logger.info(StatusStrings.DISCOVERED_DEPENDENCIES, String.join("\", \"", dependencies)); - } + private Flux processDtmi(boolean tryExpanded, String dtmi, ModelDependencyResolution resolution, Context context) { + return modelFetcher.fetchModelAsync(dtmi, repositoryUri, tryExpanded, context) + .flatMapMany(response -> { + // If the model was pre-computed, already expanded, processing of it is done. + if (response.isFromExpanded()) { + return Flux.just(response); + } - remainingWork.addAll(dependencies); - } + // If resolving dependencies isn't supported processing completes once the model response is returned. + if (resolution != ModelDependencyResolution.ENABLED) { + return Flux.just(response); + } - String parsedDtmi = metadata.getId(); - if (!parsedDtmi.equals(targetDtmi)) { - logger.error(String.format(StatusStrings.INCORRECT_DTMI_CASING, targetDtmi, parsedDtmi)); - String errorMessage = String.format(StatusStrings.GENERIC_GET_MODELS_ERROR, targetDtmi) + String.format(StatusStrings.INCORRECT_DTMI_CASING, targetDtmi, parsedDtmi); + try { + ModelMetadata metadata = new ModelsQuery(response.getDefinition()).parseModel(); + List dependencies = metadata.getDependencies(); - return Mono.error(new AzureException(errorMessage)); + if (!CoreUtils.isNullOrEmpty(dependencies)) { + logger.log(LogLevel.INFORMATIONAL, () -> + String.format(StatusStrings.DISCOVERED_DEPENDENCIES, String.join("\", \"", dependencies))); + return processAsync(tryExpanded, dependencies, resolution, context).concatWith(Flux.just(response)); } - - results.put(targetDtmi, response.getDefinition()); - return processAsync(remainingWork, resolutionOption, context, results); - + return Flux.just(response); } catch (Exception e) { return Mono.error(e); } }); } - private Queue prepareWork(Iterable dtmis) { - Queue modelsToProcess = new LinkedList<>(); + private List prepareWork(Iterable dtmis) { + List modelsToProcess = new ArrayList<>(); for (String dtmi : dtmis) { if (!DtmiConventions.isValidDtmi(dtmi)) { - logger.logExceptionAsError(new IllegalArgumentException(String.format(StatusStrings.INVALID_DTMI_FORMAT_S, dtmi))); + logger.log(LogLevel.ERROR, () -> String.format(StatusStrings.INVALID_DTMI_FORMAT_S, dtmi)); } modelsToProcess.add(dtmi); @@ -135,4 +128,22 @@ private Queue prepareWork(Iterable dtmis) { return modelsToProcess; } + + private Mono isExpandedAvailable(ModelDependencyResolution resolutionOption, Context context) { + // If ModelDependencyResolution.Enabled is requested the client will first attempt to fetch + // metadata.json content from the target repository. The metadata object includes supported features + // of the repository. + // If the metadata indicates expanded models are available. The client will try to fetch pre-computed model + // dependencies using .expanded.json. + // If the model expanded form does not exist fall back to computing model dependencies just-in-time. + if (resolutionOption == ModelDependencyResolution.ENABLED) { + return modelFetcher.fetchMetadataAsync(repositoryUri, context) + .map(result -> result.getDefinition() != null + && result.getDefinition().getFeatures() != null + && result.getDefinition().getFeatures().isExpanded()) + .onErrorReturn(false); + } + + return Mono.just(false); + } } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/StatusStrings.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/StatusStrings.java index 64e3ae3d95580..c59b3c0c91b71 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/StatusStrings.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/StatusStrings.java @@ -9,6 +9,8 @@ public class StatusStrings { public static final String PROCESSING_DTMIS = "Processing DTMI \"%s\". "; public static final String DISCOVERED_DEPENDENCIES = "Discovered dependencies \"%s\"."; public static final String FETCHING_MODEL_CONTENT = "Attempting to fetch model content from \"{}\"."; + public static final String FETCHING_METADATA_CONTENT = "Attempting to fetch repository metadata content from \"{}\"."; public static final String ERROR_FETCHING_MODEL_CONTENT = "Model file \"%s\" not found or not accessible in target repository."; + public static final String ERROR_FETCHING_METADATA_CONTENT = "Metadata file \"%s\" not found or not accessible in target repository."; public static final String INCORRECT_DTMI_CASING = "Fetched model has incorrect DTMI casing. Expected \"%s\", parsed \"%s\"."; } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java new file mode 100644 index 0000000000000..aa902d0180541 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchMetadataResult.java @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.iot.modelsrepository.implementation.models; + +import com.azure.core.annotation.Fluent; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * The {@link FetchMetadataResult} class is used for storing the result of the + * fetch repository metadata operation. It contains the metadata definition + * and path + */ +@Fluent + +public class FetchMetadataResult { + + private ModelsRepositoryMetadata definition; + private String path; + private static final ObjectMapper MAPPER = new ObjectMapper(); + + /** + * Gets the model repository's metadata definition + * + * @return Repository metadata definition + */ + public ModelsRepositoryMetadata getDefinition() { + return this.definition; + } + + /** + * Sets the model repository's metadata definition + * + * @param definition the model repository's metadata definition + * @return the {@link FetchMetadataResult} object itself + */ + public FetchMetadataResult setDefinition(String definition) throws JsonProcessingException { + this.definition = MAPPER.readValue(definition, ModelsRepositoryMetadata.class); + return this; + } + + /** + * Gets the model repository's metadata path. + * + * @return model repository's metadata path. + */ + public String getPath() { + return this.path; + } + + /** + * Sets the model repository's metadata path. + * + * @param path the model repository's metadata path. + * @return the {@link FetchMetadataResult} object itself + */ + public FetchMetadataResult setPath(String path) { + this.path = path; + return this; + } + +} diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchResult.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchModelResult.java similarity index 82% rename from sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchResult.java rename to sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchModelResult.java index 78111f08c57e7..d11f423de78d4 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchResult.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/FetchModelResult.java @@ -9,12 +9,12 @@ import java.util.Locale; /** - * The FetchResult class has the purpose of containing key elements of + * The {@link FetchModelResult} class has the purpose of containing key elements of * an IModelFetcher Fetch() operation including model definition, path and whether * it was from an expanded (pre-calculated) fetch. */ @Fluent -public class FetchResult { +public class FetchModelResult { private String definition; private String path; @@ -32,9 +32,9 @@ public String getDefinition() { * Sets the model definition * * @param definition the model definition - * @return the FetchResult object itself + * @return the {@link FetchModelResult} object itself */ - public FetchResult setDefinition(String definition) { + public FetchModelResult setDefinition(String definition) { this.definition = definition; return this; } @@ -52,9 +52,9 @@ public String getPath() { * Sets the dtmi path. * * @param path the dtmi path. - * @return the {@link FetchResult} object itself + * @return the {@link FetchModelResult} object itself */ - public FetchResult setPath(String path) { + public FetchModelResult setPath(String path) { this.path = path; return this; } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelMetadata.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelMetadata.java index 832ebfe6f3ca8..cf4739d9bbb64 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelMetadata.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelMetadata.java @@ -8,7 +8,7 @@ import java.util.List; /** - * ModelMetadata is designated to store KPIs from model parsing. + * {@link ModelMetadata} is designated to store KPIs from model parsing. */ public class ModelMetadata { private final String id; diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelsRepositoryMetadata.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelsRepositoryMetadata.java new file mode 100644 index 0000000000000..c0403a51b9192 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/ModelsRepositoryMetadata.java @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.iot.modelsrepository.implementation.models; + +/** + * {@link ModelsRepositoryMetadata} is designated to store + * information about models repository. + */ +public class ModelsRepositoryMetadata { + + private final String commitId; + private final String publishDateUtc; + private final String sourceRepo; + private final Integer totalModelCount; + private final RepositoryFeatures features; + + public ModelsRepositoryMetadata(String commitId, + String publishDateUtc, + String sourceRepo, + Integer totalModelCount, + RepositoryFeatures features) { + this.commitId = commitId; + this.publishDateUtc = publishDateUtc; + this.sourceRepo = sourceRepo; + this.totalModelCount = totalModelCount; + this.features = features; + } + + public ModelsRepositoryMetadata() { + this.commitId = null; + this.publishDateUtc = null; + this.sourceRepo = null; + this.totalModelCount = null; + this.features = null; + } + + public String getCommitId() { + return this.commitId; + } + + public String getPublishDateUtc() { + return this.publishDateUtc; + } + + public String getSourceRepo() { + return this.sourceRepo; + } + + public Integer getTotalModelCount() { + return this.totalModelCount; + } + + public RepositoryFeatures getFeatures() { + return this.features; + } +} diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/RepositoryFeatures.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/RepositoryFeatures.java new file mode 100644 index 0000000000000..8d58c8ec14056 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/main/java/com/azure/iot/modelsrepository/implementation/models/RepositoryFeatures.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.iot.modelsrepository.implementation.models; + +/** + * {@link RepositoryFeatures} is designated to store + * attributes which apply to all models in the repository + */ +public class RepositoryFeatures { + private final boolean expanded; + private final boolean index; + + public RepositoryFeatures(boolean expanded, boolean index) { + this.expanded = expanded; + this.index = index; + } + + public RepositoryFeatures() { + this.expanded = false; + this.index = false; + } + + public boolean isIndex() { + return index; + } + + public boolean isExpanded() { + return expanded; + } +} diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md index ec8476aabca03..33ac8717a2959 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/README.md @@ -18,7 +18,7 @@ The samples project demonstrates the following: ```java // When no URI is provided for instantiation, the Azure IoT Models Repository global endpoint // https://devicemodels.azure.com/ is used and the model dependency resolution -// configuration is set to TRY_FROM_EXPANDED. +// configuration is set to ENABLED. ModelsRepositoryAsyncClient asyncClient = new ModelsRepositoryClientBuilder() .buildAsyncClient(); diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java index 4a2f8501dc907..e1601bba44a01 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/samples/java/com/azure/iot/core/ModelResolutionSamples.java @@ -21,7 +21,7 @@ public class ModelResolutionSamples { public static void clientInitializationSamples() { // When no URI is provided for instantiation, the Azure IoT Models Repository global endpoint // https://devicemodels.azure.com/ is used and the model dependency resolution - // configuration is set to TryFromExpanded. + // configuration is set to Enabled. ModelsRepositoryAsyncClient asyncClient = new ModelsRepositoryClientBuilder() .buildAsyncClient(); @@ -70,7 +70,7 @@ public static void getModelsFromGlobalRepository() throws InterruptedException { .buildAsyncClient(); // The output of getModels will include at least the definition for the target dtmi. - // If the model dependency resolution configuration is not disabled, then models in which the + // If the model dependency resolution configuration is enabled, then models in which the // target dtmi depends on will also be included in the returned Map. String targetDtmi = "dtmi:com:example:TemperatureController;1"; @@ -92,7 +92,7 @@ public static void getMultipleModelsFromGlobalRepository() throws InterruptedExc // When given an Iterable of dtmis, the output of getModels() will include at // least the definitions of each dtmi enumerated in the Iterable. - // If the model dependency resolution configuration is not disabled, then models in which each + // If the model dependency resolution configuration is enabled, then models in which each // enumerated dtmi depends on will also be included in the returned Map. Iterable dtmis = Arrays.asList("dtmi:com:example:TemperatureController;1", "dtmi:com:example:azuresphere:sampledevice;1"); @@ -115,7 +115,7 @@ public static void getModelsFromLocalRepository() throws InterruptedException { .buildAsyncClient(); // The output of getModels will include at least the definition for the target dtmi. - // If the model dependency resolution configuration is not disabled, then models in which the + // If the model dependency resolution configuration is enabled, then models in which the // target dtmi depends on will also be included in the returned Map. String targetDtmi = "dtmi:com:example:TemperatureController;1"; diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java index e6a85d3ca2e0f..ddabff67f62c2 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/DtmiConventionTests.java @@ -53,6 +53,27 @@ public void getModelUriTests(String repository, String expectedUri) { Assertions.assertEquals(expectedUri, modelUri.toString()); } + @ParameterizedTest + @CsvSource({ + "https://localhost/repository/, https://localhost/repository/metadata.json", + "https://localhost/REPOSITORY, https://localhost/REPOSITORY/metadata.json", + "file:///path/to/repository/, file:///path/to/repository/metadata.json", + "file://path/to/RepoSitory, file://path/to/RepoSitory/metadata.json", + "C:/path/to/repository/, C:/path/to/repository/metadata.json", + "//server//repository, //server//repository/metadata.json" + }) + public void getMetadataUriTests(String repository, String expectedUri) { + URI repositoryUri = TestHelper.convertToUri(repository); + + if (expectedUri == null || expectedUri.isEmpty()) { + Assertions.assertThrows(IllegalArgumentException.class, () -> DtmiConventions.getMetadataUri(repositoryUri)); + return; + } + + URI metadataUri = DtmiConventions.getMetadataUri(repositoryUri); + Assertions.assertEquals(expectedUri, metadataUri.toString()); + } + @ParameterizedTest @CsvSource({ "dtmi:com:example:Thermostat;1, true", diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java index 7d7ab8e98fb9b..613b3c8d32cf4 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/ModelRepositoryIntegrationTests.java @@ -22,7 +22,7 @@ class ModelRepositoryIntegrationTests extends ModelsRepositoryTestBase { @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) @MethodSource("com.azure.iot.modelsrepository.TestHelper#getTestParameters") public void getModelsSingleDtmiNoDependencies(HttpClient httpClient, ModelsRepositoryServiceVersion serviceVersion, String repositoryUri) throws URISyntaxException { - final String dtmi = "dtmi:com:example:Thermostat;1"; + String dtmi = "dtmi:com:example:Thermostat;1"; ModelsRepositoryAsyncClient client = getAsyncClient(httpClient, serviceVersion, repositoryUri); diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java index 736cf59272970..03bd3dcf97251 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/java/com/azure/iot/modelsrepository/TestHelper.java @@ -22,7 +22,9 @@ class TestHelper { public static final String DISPLAY_NAME_WITH_ARGUMENTS = "{displayName} with [{arguments}]"; private static final String AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS = "AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS"; - private static final String LOCAL_TEST_REPOSITORY_PATH = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/").replace("\\", "/"); + private static final String LOCAL_TEST_REPOSITORY_PATH_WITH_METADATA = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/metadataModelsrepo/").replace("\\", "/"); + private static final String LOCAL_TEST_REPOSITORY_NO_METADATA_PATH = (System.getProperty("user.dir") + "/src/test/resources/TestModelRepo/").replace("\\", "/"); + public static final String MODELS_REPOSITORY_NO_METADATA_ENDPOINT = "https://raw.githubusercontent.com/Azure/iot-plugandplay-models/main"; private static final String SERVICE_VERSION_FROM_ENV = Configuration.getGlobalConfiguration().get(AZURE_IOT_MODELSREPOSITORY_TEST_SERVICE_VERSIONS); @@ -51,7 +53,9 @@ static Stream getTestParameters() { static Stream getApplicableRepositoryUris() { ArrayList endpointList = new ArrayList<>(); endpointList.add(ModelsRepositoryConstants.DEFAULT_MODELS_REPOSITORY_ENDPOINT); - endpointList.add(LOCAL_TEST_REPOSITORY_PATH); + endpointList.add(LOCAL_TEST_REPOSITORY_PATH_WITH_METADATA); + endpointList.add(MODELS_REPOSITORY_NO_METADATA_ENDPOINT); + endpointList.add(LOCAL_TEST_REPOSITORY_NO_METADATA_PATH); return StreamSupport.stream(endpointList.spliterator(), false); } diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-1.json new file mode 100644 index 0000000000000..8a37e6d2c2c37 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-1.json @@ -0,0 +1,64 @@ +{ + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "@type": "Interface", + "displayName": "Device Information", + "contents": [ + { + "@type": "Property", + "name": "manufacturer", + "displayName": "Manufacturer", + "schema": "string", + "description": "Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso." + }, + { + "@type": "Property", + "name": "model", + "displayName": "Device model", + "schema": "string", + "description": "Device model name or ID. Ex. Surface Book 2." + }, + { + "@type": "Property", + "name": "swVersion", + "displayName": "Software version", + "schema": "string", + "description": "Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45" + }, + { + "@type": "Property", + "name": "osName", + "displayName": "Operating system name", + "schema": "string", + "description": "Name of the operating system on the device. Ex. Windows 10 IoT Core." + }, + { + "@type": "Property", + "name": "processorArchitecture", + "displayName": "Processor architecture", + "schema": "string", + "description": "Architecture of the processor on the device. Ex. x64 or ARM." + }, + { + "@type": "Property", + "name": "processorManufacturer", + "displayName": "Processor manufacturer", + "schema": "string", + "description": "Name of the manufacturer of the processor on the device. Ex. Intel." + }, + { + "@type": "Property", + "name": "totalStorage", + "displayName": "Total storage", + "schema": "double", + "description": "Total available storage on the device in kilobytes. Ex. 2048000 kilobytes." + }, + { + "@type": "Property", + "name": "totalMemory", + "displayName": "Total memory", + "schema": "double", + "description": "Total available memory on the device in kilobytes. Ex. 256000 kilobytes." + } + ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-2.json new file mode 100644 index 0000000000000..d35b8a3e3a1d5 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/azure/devicemanagement/deviceinformation-2.json @@ -0,0 +1,16 @@ +{ + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:azure:DeviceManagement:DeviceInformation;2", + "@type": "Interface", + "extends": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "displayName": "Device Information", + "contents": [ + { + "@type": "Property", + "name": "osKernelVersion", + "displayName": "OS Kernel Version", + "schema": "string", + "description": "OS Kernel Version. Ex. Linux 4.15.0-54-generic x86_64." + } + ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-1.json new file mode 100644 index 0000000000000..85424e8a229e6 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-1.json @@ -0,0 +1,56 @@ +{ + "@id": "dtmi:com:example:base;1", + "@type": "Interface", + "contents": [ + { + "@type": "Property", + "name": "baseSerialNumber", + "schema": "string" + } + ], + "displayName": { + "en": "mybaseProp" + }, + "extends": [ + { + "@id": "dtmi:com:example:basic;1", + "@type": "Interface", + "contents": [ + { + "@type": "Property", + "name": "serialNumber", + "schema": "string", + "writable": false + }, + { + "@type": [ + "Telemetry", + "Temperature" + ], + "displayName": { + "en": "temperature" + }, + "name": "temperature", + "schema": "double", + "unit": "degreeCelsius" + }, + { + "@type": "Property", + "displayName": { + "en": "targetTemperature" + }, + "name": "targetTemperature", + "schema": "double", + "writable": true + } + ], + "displayName": { + "en": "Basic" + } + } + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-2.json new file mode 100644 index 0000000000000..29accafcc252e --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/base-2.json @@ -0,0 +1,57 @@ +{ + "@id": "dtmi:com:example:base;2", + "@type": "Interface", + "contents": [ + { + "@type": "Property", + "name": "baseSerialNumber", + "schema": "string" + } + ], + "displayName": { + "en": "mybaseProp" + }, + "extends": [ + { + "@id": "dtmi:com:example:basic;1", + "@type": "Interface", + "contents": [ + { + "@type": "Property", + "name": "serialNumber", + "schema": "string", + "writable": false + }, + { + "@type": [ + "Telemetry", + "Temperature" + ], + "displayName": { + "en": "temperature" + }, + "name": "temperature", + "schema": "double", + "unit": "degreeCelsius" + }, + { + "@type": "Property", + "displayName": { + "en": "targetTemperature" + }, + "name": "targetTemperature", + "schema": "double", + "writable": true + } + ], + "displayName": { + "en": "Basic" + } + }, + "dtmi:com:example:Freezer;1" + ], + "@context": [ + "dtmi:iotcentral:context;2", + "dtmi:dtdl:context;2" + ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/building-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/building-1.json new file mode 100644 index 0000000000000..c8b6bc6f73756 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/building-1.json @@ -0,0 +1,19 @@ +{ + "@id": "dtmi:com:example:Building;1", + "@type": "Interface", + "displayName": "Building", + "contents": [ + { + "@type": "Property", + "name": "name", + "schema": "string", + "writable": true + }, + { + "@type": "Relationship", + "name": "contains", + "target": "dtmi:com:example:Room;1" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/camera-3.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/camera-3.json new file mode 100644 index 0000000000000..f912746c0040d --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/camera-3.json @@ -0,0 +1,13 @@ +{ + "@id": "dtmi:com:example:Camera;3", + "@type": "Interface", + "displayName": "Phone", + "contents": [ + { + "@type": "Component", + "name": "deviceInfo", + "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/coldstorage-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/coldstorage-1.json new file mode 100644 index 0000000000000..a3b8466118a90 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/coldstorage-1.json @@ -0,0 +1,13 @@ +{ + "@id": "dtmi:com:example:ColdStorage;1", + "@type": "Interface", + "extends": ["dtmi:com:example:Room;1", "dtmi:com:example:Freezer;1"], + "contents": [ + { + "@type": "Property", + "name": "capacity", + "schema": "integer" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/conferenceroom-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/conferenceroom-1.json new file mode 100644 index 0000000000000..2e756ee73b6e9 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/conferenceroom-1.json @@ -0,0 +1,13 @@ +{ + "@id": "dtmi:com:example:ConferenceRoom;1", + "@type": "Interface", + "extends": "dtmi:com:example:Room;1", + "contents": [ + { + "@type": "Property", + "name": "capacity", + "schema": "integer" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/danglingexpanded-1.expanded.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/danglingexpanded-1.expanded.json new file mode 100644 index 0000000000000..93126c749ce9a --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/danglingexpanded-1.expanded.json @@ -0,0 +1,215 @@ +[ + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:com:example:DanglingExpanded;1", + "@type": "Interface", + "displayName": "Valid expanded model with no root model.", + "description": "Device with two thermostats and remote reboot.", + "contents": [ + { + "@type": [ + "Telemetry", + "DataSize" + ], + "name": "workingSet", + "displayName": "Working Set", + "description": "Current working set of the device memory in KiB.", + "schema": "double", + "unit": "kibibyte" + }, + { + "@type": "Property", + "name": "serialNumber", + "displayName": "Serial Number", + "description": "Serial number of the device.", + "schema": "string" + }, + { + "@type": "Command", + "name": "reboot", + "displayName": "Reboot", + "description": "Reboots the device after waiting the number of seconds specified.", + "request": { + "name": "delay", + "displayName": "Delay", + "description": "Number of seconds to wait before rebooting the device.", + "schema": "integer" + } + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat1", + "displayName": "Thermostat One", + "description": "Thermostat One of Two." + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat2", + "displayName": "Thermostat Two", + "description": "Thermostat Two of Two." + }, + { + "@type": "Component", + "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "name": "deviceInformation", + "displayName": "Device Information interface", + "description": "Optional interface with basic device hardware information." + } + ] + }, + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:com:example:Thermostat;1", + "@type": "Interface", + "displayName": "Thermostat", + "description": "Reports current temperature and provides desired temperature control.", + "contents": [ + { + "@type": [ + "Telemetry", + "Temperature" + ], + "name": "temperature", + "displayName": "Temperature", + "description": "Temperature in degrees Celsius.", + "schema": "double", + "unit": "degreeCelsius" + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "targetTemperature", + "schema": "double", + "displayName": "Target Temperature", + "description": "Allows to remotely specify the desired target temperature.", + "unit": "degreeCelsius", + "writable": true + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "maxTempSinceLastReboot", + "schema": "double", + "unit": "degreeCelsius", + "displayName": "Max temperature since last reboot.", + "description": "Returns the max temperature since last device reboot." + }, + { + "@type": "Command", + "name": "getMaxMinReport", + "displayName": "Get Max-Min report.", + "description": "This command returns the max, min and average temperature from the specified time to the current time.", + "request": { + "name": "since", + "displayName": "Since", + "description": "Period to return the max-min report.", + "schema": "dateTime" + }, + "response": { + "name": "tempReport", + "displayName": "Temperature Report", + "schema": { + "@type": "Object", + "fields": [ + { + "name": "maxTemp", + "displayName": "Max temperature", + "schema": "double" + }, + { + "name": "minTemp", + "displayName": "Min temperature", + "schema": "double" + }, + { + "name": "avgTemp", + "displayName": "Average Temperature", + "schema": "double" + }, + { + "name": "startTime", + "displayName": "Start Time", + "schema": "dateTime" + }, + { + "name": "endTime", + "displayName": "End Time", + "schema": "dateTime" + } + ] + } + } + } + ] + }, + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "@type": "Interface", + "displayName": "Device Information", + "contents": [ + { + "@type": "Property", + "name": "manufacturer", + "displayName": "Manufacturer", + "schema": "string", + "description": "Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso." + }, + { + "@type": "Property", + "name": "model", + "displayName": "Device model", + "schema": "string", + "description": "Device model name or ID. Ex. Surface Book 2." + }, + { + "@type": "Property", + "name": "swVersion", + "displayName": "Software version", + "schema": "string", + "description": "Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45" + }, + { + "@type": "Property", + "name": "osName", + "displayName": "Operating system name", + "schema": "string", + "description": "Name of the operating system on the device. Ex. Windows 10 IoT Core." + }, + { + "@type": "Property", + "name": "processorArchitecture", + "displayName": "Processor architecture", + "schema": "string", + "description": "Architecture of the processor on the device. Ex. x64 or ARM." + }, + { + "@type": "Property", + "name": "processorManufacturer", + "displayName": "Processor manufacturer", + "schema": "string", + "description": "Name of the manufacturer of the processor on the device. Ex. Intel." + }, + { + "@type": "Property", + "name": "totalStorage", + "displayName": "Total storage", + "schema": "double", + "description": "Total available storage on the device in kilobytes. Ex. 2048000 kilobytes." + }, + { + "@type": "Property", + "name": "totalMemory", + "displayName": "Total memory", + "schema": "double", + "description": "Total available memory on the device in kilobytes. Ex. 256000 kilobytes." + } + ] + } +] diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/freezer-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/freezer-1.json new file mode 100644 index 0000000000000..6006b66732991 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/freezer-1.json @@ -0,0 +1,12 @@ +{ + "@id": "dtmi:com:example:Freezer;1", + "@type": "Interface", + "contents": [ + { + "@type": "Component", + "name": "deviceInfo", + "schema": "dtmi:com:example:Thermostat;1" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/incompleteexpanded-1.expanded.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/incompleteexpanded-1.expanded.json new file mode 100644 index 0000000000000..1688ef4c0e3c5 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/incompleteexpanded-1.expanded.json @@ -0,0 +1,151 @@ +[ + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:com:example:IncompleteExpanded;1", + "@type": "Interface", + "displayName": "Incomplete expanded Temperature Controller", + "description": "Device with two thermostats and remote reboot.", + "contents": [ + { + "@type": [ + "Telemetry", + "DataSize" + ], + "name": "workingSet", + "displayName": "Working Set", + "description": "Current working set of the device memory in KiB.", + "schema": "double", + "unit": "kibibyte" + }, + { + "@type": "Property", + "name": "serialNumber", + "displayName": "Serial Number", + "description": "Serial number of the device.", + "schema": "string" + }, + { + "@type": "Command", + "name": "reboot", + "displayName": "Reboot", + "description": "Reboots the device after waiting the number of seconds specified.", + "request": { + "name": "delay", + "displayName": "Delay", + "description": "Number of seconds to wait before rebooting the device.", + "schema": "integer" + } + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat1", + "displayName": "Thermostat One", + "description": "Thermostat One of Two." + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat2", + "displayName": "Thermostat Two", + "description": "Thermostat Two of Two." + }, + { + "@type": "Component", + "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "name": "deviceInformation", + "displayName": "Device Information interface", + "description": "Optional interface with basic device hardware information." + } + ] + }, + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:com:example:Thermostat;1", + "@type": "Interface", + "displayName": "Thermostat", + "description": "Reports current temperature and provides desired temperature control.", + "contents": [ + { + "@type": [ + "Telemetry", + "Temperature" + ], + "name": "temperature", + "displayName": "Temperature", + "description": "Temperature in degrees Celsius.", + "schema": "double", + "unit": "degreeCelsius" + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "targetTemperature", + "schema": "double", + "displayName": "Target Temperature", + "description": "Allows to remotely specify the desired target temperature.", + "unit": "degreeCelsius", + "writable": true + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "maxTempSinceLastReboot", + "schema": "double", + "unit": "degreeCelsius", + "displayName": "Max temperature since last reboot.", + "description": "Returns the max temperature since last device reboot." + }, + { + "@type": "Command", + "name": "getMaxMinReport", + "displayName": "Get Max-Min report.", + "description": "This command returns the max, min and average temperature from the specified time to the current time.", + "request": { + "name": "since", + "displayName": "Since", + "description": "Period to return the max-min report.", + "schema": "dateTime" + }, + "response": { + "name": "tempReport", + "displayName": "Temperature Report", + "schema": { + "@type": "Object", + "fields": [ + { + "name": "maxTemp", + "displayName": "Max temperature", + "schema": "double" + }, + { + "name": "minTemp", + "displayName": "Min temperature", + "schema": "double" + }, + { + "name": "avgTemp", + "displayName": "Average Temperature", + "schema": "double" + }, + { + "name": "startTime", + "displayName": "Start Time", + "schema": "dateTime" + }, + { + "name": "endTime", + "displayName": "End Time", + "schema": "dateTime" + } + ] + } + } + } + ] + } +] diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-1.json new file mode 100644 index 0000000000000..4f18d7b176584 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-1.json @@ -0,0 +1,13 @@ +{ + "@id": "dtmi:com:example:invalidmodel;1", + "@type": "Interface", + "displayName": "Phone", + "contents": [ + { + "@type": "Component", + "name": "deviceInfo", + "schema": "dtmi:azure:fakeDeviceManagement:FakeDeviceInformation;2" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-2.json new file mode 100644 index 0000000000000..61443734cd900 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/invalidmodel-2.json @@ -0,0 +1,23 @@ +{ + "@id": "dtmi:com:example:Phone;2", + "@type": "Interfacez", + "displayName": "Phone", + "contentsz": [ + { + "@type": "Component", + "name": "frontCamera", + "schema": "dtmi:com:example:Camera;3" + }, + { + "@type": "Component", + "name": "backCamera", + "schema": "dtmi:com:example:Camera;3" + }, + { + "@type": "Component", + "name": "deviceInfo", + "schema": "dtmi:azure:deviceManagement:DeviceInformation;2" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/phone-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/phone-2.json new file mode 100644 index 0000000000000..26c7efbdedc01 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/phone-2.json @@ -0,0 +1,23 @@ +{ + "@id": "dtmi:com:example:Phone;2", + "@type": "Interface", + "displayName": "Phone", + "contents": [ + { + "@type": "Component", + "name": "frontCamera", + "schema": "dtmi:com:example:Camera;3" + }, + { + "@type": "Component", + "name": "backCamera", + "schema": "dtmi:com:example:Camera;3" + }, + { + "@type": "Component", + "name": "deviceInfo", + "schema": "dtmi:azure:DeviceManagement:DeviceInformation;2" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/room-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/room-1.json new file mode 100644 index 0000000000000..1a07edec4d984 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/room-1.json @@ -0,0 +1,12 @@ +{ + "@id": "dtmi:com:example:Room;1", + "@type": "Interface", + "contents": [ + { + "@type": "Property", + "name": "occupied", + "schema": "boolean" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.expanded.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.expanded.json new file mode 100644 index 0000000000000..14e8e294189e3 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.expanded.json @@ -0,0 +1,215 @@ +[ + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:com:example:TemperatureController;1", + "@type": "Interface", + "displayName": "Temperature Controller", + "description": "Device with two thermostats and remote reboot.", + "contents": [ + { + "@type": [ + "Telemetry", + "DataSize" + ], + "name": "workingSet", + "displayName": "Working Set", + "description": "Current working set of the device memory in KiB.", + "schema": "double", + "unit": "kibibyte" + }, + { + "@type": "Property", + "name": "serialNumber", + "displayName": "Serial Number", + "description": "Serial number of the device.", + "schema": "string" + }, + { + "@type": "Command", + "name": "reboot", + "displayName": "Reboot", + "description": "Reboots the device after waiting the number of seconds specified.", + "request": { + "name": "delay", + "displayName": "Delay", + "description": "Number of seconds to wait before rebooting the device.", + "schema": "integer" + } + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat1", + "displayName": "Thermostat One", + "description": "Thermostat One of Two." + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat2", + "displayName": "Thermostat Two", + "description": "Thermostat Two of Two." + }, + { + "@type": "Component", + "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "name": "deviceInformation", + "displayName": "Device Information interface", + "description": "Optional interface with basic device hardware information." + } + ] + }, + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:com:example:Thermostat;1", + "@type": "Interface", + "displayName": "Thermostat", + "description": "Reports current temperature and provides desired temperature control.", + "contents": [ + { + "@type": [ + "Telemetry", + "Temperature" + ], + "name": "temperature", + "displayName": "Temperature", + "description": "Temperature in degrees Celsius.", + "schema": "double", + "unit": "degreeCelsius" + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "targetTemperature", + "schema": "double", + "displayName": "Target Temperature", + "description": "Allows to remotely specify the desired target temperature.", + "unit": "degreeCelsius", + "writable": true + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "maxTempSinceLastReboot", + "schema": "double", + "unit": "degreeCelsius", + "displayName": "Max temperature since last reboot.", + "description": "Returns the max temperature since last device reboot." + }, + { + "@type": "Command", + "name": "getMaxMinReport", + "displayName": "Get Max-Min report.", + "description": "This command returns the max, min and average temperature from the specified time to the current time.", + "request": { + "name": "since", + "displayName": "Since", + "description": "Period to return the max-min report.", + "schema": "dateTime" + }, + "response": { + "name": "tempReport", + "displayName": "Temperature Report", + "schema": { + "@type": "Object", + "fields": [ + { + "name": "maxTemp", + "displayName": "Max temperature", + "schema": "double" + }, + { + "name": "minTemp", + "displayName": "Min temperature", + "schema": "double" + }, + { + "name": "avgTemp", + "displayName": "Average Temperature", + "schema": "double" + }, + { + "name": "startTime", + "displayName": "Start Time", + "schema": "dateTime" + }, + { + "name": "endTime", + "displayName": "End Time", + "schema": "dateTime" + } + ] + } + } + } + ] + }, + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "@type": "Interface", + "displayName": "Device Information", + "contents": [ + { + "@type": "Property", + "name": "manufacturer", + "displayName": "Manufacturer", + "schema": "string", + "description": "Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso." + }, + { + "@type": "Property", + "name": "model", + "displayName": "Device model", + "schema": "string", + "description": "Device model name or ID. Ex. Surface Book 2." + }, + { + "@type": "Property", + "name": "swVersion", + "displayName": "Software version", + "schema": "string", + "description": "Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45" + }, + { + "@type": "Property", + "name": "osName", + "displayName": "Operating system name", + "schema": "string", + "description": "Name of the operating system on the device. Ex. Windows 10 IoT Core." + }, + { + "@type": "Property", + "name": "processorArchitecture", + "displayName": "Processor architecture", + "schema": "string", + "description": "Architecture of the processor on the device. Ex. x64 or ARM." + }, + { + "@type": "Property", + "name": "processorManufacturer", + "displayName": "Processor manufacturer", + "schema": "string", + "description": "Name of the manufacturer of the processor on the device. Ex. Intel." + }, + { + "@type": "Property", + "name": "totalStorage", + "displayName": "Total storage", + "schema": "double", + "description": "Total available storage on the device in kilobytes. Ex. 2048000 kilobytes." + }, + { + "@type": "Property", + "name": "totalMemory", + "displayName": "Total memory", + "schema": "double", + "description": "Total available memory on the device in kilobytes. Ex. 256000 kilobytes." + } + ] + } +] \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.json new file mode 100644 index 0000000000000..c455ddf8bae67 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/temperaturecontroller-1.json @@ -0,0 +1,60 @@ +{ + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:com:example:TemperatureController;1", + "@type": "Interface", + "displayName": "Temperature Controller", + "description": "Device with two thermostats and remote reboot.", + "contents": [ + { + "@type": [ + "Telemetry", + "DataSize" + ], + "name": "workingSet", + "displayName": "Working Set", + "description": "Current working set of the device memory in KiB.", + "schema": "double", + "unit": "kibibyte" + }, + { + "@type": "Property", + "name": "serialNumber", + "displayName": "Serial Number", + "description": "Serial number of the device.", + "schema": "string" + }, + { + "@type": "Command", + "name": "reboot", + "displayName": "Reboot", + "description": "Reboots the device after waiting the number of seconds specified.", + "request": { + "name": "delay", + "displayName": "Delay", + "description": "Number of seconds to wait before rebooting the device.", + "schema": "integer" + } + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat1", + "displayName": "Thermostat One", + "description": "Thermostat One of Two." + }, + { + "@type": "Component", + "schema": "dtmi:com:example:Thermostat;1", + "name": "thermostat2", + "displayName": "Thermostat Two", + "description": "Thermostat Two of Two." + }, + { + "@type": "Component", + "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1", + "name": "deviceInformation", + "displayName": "Device Information interface", + "description": "Optional interface with basic device hardware information." + } + ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/thermostat-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/thermostat-1.json new file mode 100644 index 0000000000000..315a307bbcb38 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/com/example/thermostat-1.json @@ -0,0 +1,19 @@ +{ + "@id": "dtmi:com:example:Thermostat;1", + "@type": "Interface", + "displayName": "Thermostat", + "contents": [ + { + "@type": "Telemetry", + "name": "temp", + "schema": "double" + }, + { + "@type": "Property", + "name": "setPointTemp", + "writable": true, + "schema": "double" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-1.json new file mode 100644 index 0000000000000..33c9554664a60 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-1.json @@ -0,0 +1,31 @@ +{ + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:company:demodevice;1", + "@type": "Interface", + "displayName": "demodevice", + "contents": [ + { + "@type": "Component", + "name": "c1", + "schema": "dtmi:azure:deviceManagement:DeviceInformation;1" + }, + { + "@type": "Telemetry", + "name": "temperature", + "schema": "double" + }, + { + "@type": "Property", + "name": "deviceStatus", + "schema": "string" + }, + { + "@type": "Command", + "name": "reboot", + "request": { + "name": "delay", + "schema": "integer" + } + } + ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-2.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-2.json new file mode 100644 index 0000000000000..9d9b3bd2322aa --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/company/demodevice-2.json @@ -0,0 +1,31 @@ +{ + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:company:demodevice;1", + "@type": "Interface", + "displayName": "demodevice", + "contents": [ + { + "@type": "Component", + "name": "c1", + "schema": "dtmi:azure:DeviceManagement:DeviceInformation;1" + }, + { + "@type": "Telemetry", + "name": "temperature", + "schema": "double" + }, + { + "@type": "Property", + "name": "deviceStatus", + "schema": "string" + }, + { + "@type": "Command", + "name": "reboot", + "request": { + "name": "delay", + "schema": "integer" + } + } + ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/badfilepath-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/badfilepath-1.json new file mode 100644 index 0000000000000..6006b66732991 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/badfilepath-1.json @@ -0,0 +1,12 @@ +{ + "@id": "dtmi:com:example:Freezer;1", + "@type": "Interface", + "contents": [ + { + "@type": "Component", + "name": "deviceInfo", + "schema": "dtmi:com:example:Thermostat;1" + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/emptyarray-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/emptyarray-1.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/emptyarray-1.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/namespaceconflict-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/namespaceconflict-1.json new file mode 100644 index 0000000000000..6f2df812a67fa --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/namespaceconflict-1.json @@ -0,0 +1,37 @@ +{ + "@id": "dtmi:strict:namespaceconflict;1", + "@type": "Interface", + "contents": [ + { + "@type": "Telemetry", + "name": "accelerometer1", + "schema": "dtmi:com:example:acceleration;1" + }, + { + "@type": "Telemetry", + "name": "accelerometer2", + "schema": "dtmi:com:example:acceleration;1" + } + ], + "schemas": [ + { + "@id": "dtmi:com:example:acceleration;1", + "@type": "Object", + "fields": [ + { + "name": "x", + "schema": "double" + }, + { + "name": "y", + "schema": "double" + }, + { + "name": "z", + "schema": "double" + } + ] + } + ], + "@context": "dtmi:dtdl:context;2" +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/nondtdl-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/nondtdl-1.json new file mode 100644 index 0000000000000..b25ba2ac3af65 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/nondtdl-1.json @@ -0,0 +1 @@ +"content" \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/unsupportedrootarray-1.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/unsupportedrootarray-1.json new file mode 100644 index 0000000000000..1f282307a8c3c --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/dtmi/strict/unsupportedrootarray-1.json @@ -0,0 +1,91 @@ +[ + { + "@context": "dtmi:dtdl:context;2", + "@id": "dtmi:strict:unsupportedrootarray;1", + "@type": "Interface", + "displayName": "Thermostat", + "description": "Reports current temperature and provides desired temperature control.", + "contents": [ + { + "@type": [ + "Telemetry", + "Temperature" + ], + "name": "temperature", + "displayName": "Temperature", + "description": "Temperature in degrees Celsius.", + "schema": "double", + "unit": "degreeCelsius" + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "targetTemperature", + "schema": "double", + "displayName": "Target Temperature", + "description": "Allows to remotely specify the desired target temperature.", + "unit": "degreeCelsius", + "writable": true + }, + { + "@type": [ + "Property", + "Temperature" + ], + "name": "maxTempSinceLastReboot", + "schema": "double", + "unit": "degreeCelsius", + "displayName": "Max temperature since last reboot.", + "description": "Returns the max temperature since last device reboot." + }, + { + "@type": "Command", + "name": "getMaxMinReport", + "displayName": "Get Max-Min report.", + "description": "This command returns the max, min and average temperature from the specified time to the current time.", + "request": { + "name": "since", + "displayName": "Since", + "description": "Period to return the max-min report.", + "schema": "dateTime" + }, + "response": { + "name": "tempReport", + "displayName": "Temperature Report", + "schema": { + "@type": "Object", + "fields": [ + { + "name": "maxTemp", + "displayName": "Max temperature", + "schema": "double" + }, + { + "name": "minTemp", + "displayName": "Min temperature", + "schema": "double" + }, + { + "name": "avgTemp", + "displayName": "Average Temperature", + "schema": "double" + }, + { + "name": "startTime", + "displayName": "Start Time", + "schema": "dateTime" + }, + { + "name": "endTime", + "displayName": "End Time", + "schema": "dateTime" + } + ] + } + } + } + ] + } +] \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/metadata.json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/metadata.json new file mode 100644 index 0000000000000..93e3ed185af74 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/TestModelRepo/metadataModelsrepo/metadata.json @@ -0,0 +1,10 @@ +{ + "commitId": "f49444d5deefa369300c7653b5958f9907da550a", + "features": { + "expanded": true, + "index": true + }, + "publishDateUtc": "2021-09-16T23:01:01.885362+00:00", + "sourceRepo": "Azure/iot-plugandplay-models", + "totalModelCount": 19010 +} diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json index 338f1eb18a972..91b113ce183c8 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[1].json @@ -1,59 +1,119 @@ { "networkCallRecords" : [ { "Method" : "GET", - "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json", + "Uri" : "https://REDACTED.azure.com/%2Fmetadata.json", "Headers" : { - "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)", - "x-ms-client-request-id" : "7b951b25-6790-4d63-ab89-fd20e797ce2a" + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "25af01c9-d572-4418-9294-027f46a32981" }, "Response" : { "X-Cache" : "HIT", + "content-length" : "253", "x-ms-version" : "2018-03-28", - "Server" : "ECAcc (sed/E10D)", + "Server" : "ECAcc (sed/E179)", "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", - "Last-Modified" : "Tue, 15 Dec 2020 21:10:59 GMT", + "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT", "retry-after" : "0", "StatusCode" : "200", "Access-Control-Allow-Headers" : "*", - "Date" : "Tue, 23 Mar 2021 22:20:07 GMT", - "Content-MD5" : "Vw1WdSQoTBOhmiB9XXUwsw==", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==", "Accept-Ranges" : "bytes", "Access-Control-Expose-Headers" : "*", - "Etag" : "\"0x8D8A13DEBC85F73\"", + "Cache-Control" : "max-age=600", + "Etag" : "\"0x8D988F70ADF0EEF\"", "x-ms-error-code" : "ConditionNotMet", - "Content-Length" : "2218", - "x-ms-request-id" : "36be9211-f01e-0028-1238-1cfe51000000", - "Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]", - "Age" : "437504", + "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT", + "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000", + "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}", + "Age" : "15", "Content-Type" : "application/json" }, "Exception" : null }, { "Method" : "GET", - "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json", + "Uri" : "https://REDACTED.azure.com/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json", "Headers" : { - "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)", - "x-ms-client-request-id" : "57490341-ee0b-4248-8c2e-9a79b7aa0fa7" + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "c3dde8f2-c996-49a3-87f5-1c9272c9d4c8" }, "Response" : { "X-Cache" : "HIT", + "content-length" : "2218", "x-ms-version" : "2018-03-28", - "Server" : "ECAcc (sed/E10D)", + "Server" : "ECAcc (sed/E16F)", "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", - "Last-Modified" : "Tue, 15 Dec 2020 21:10:59 GMT", + "Last-Modified" : "Wed, 14 Apr 2021 00:08:03 GMT", "retry-after" : "0", "StatusCode" : "200", "Access-Control-Allow-Headers" : "*", - "Date" : "Tue, 23 Mar 2021 22:20:07 GMT", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", "Content-MD5" : "Vw1WdSQoTBOhmiB9XXUwsw==", "Accept-Ranges" : "bytes", "Access-Control-Expose-Headers" : "*", - "Etag" : "\"0x8D8A13DEBC85F73\"", + "Etag" : "\"0x8D8FED95F570217\"", + "x-ms-request-id" : "8f0a7681-b01e-0021-1b52-ba22ba000000", + "Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]", + "Age" : "67480", + "Content-Type" : "application/json" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.azure.com/%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "99d53076-3314-4c8c-ac26-f5255a3ce57b" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "253", + "x-ms-version" : "2018-03-28", + "Server" : "ECAcc (sed/E179)", + "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", + "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Access-Control-Allow-Headers" : "*", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==", + "Accept-Ranges" : "bytes", + "Access-Control-Expose-Headers" : "*", + "Cache-Control" : "max-age=600", + "Etag" : "\"0x8D988F70ADF0EEF\"", "x-ms-error-code" : "ConditionNotMet", - "Content-Length" : "2218", - "x-ms-request-id" : "36be9211-f01e-0028-1238-1cfe51000000", + "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT", + "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000", + "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}", + "Age" : "15", + "Content-Type" : "application/json" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.azure.com/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.expanded.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "5863f9ee-2fb7-446c-aee2-03167295300f" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "2218", + "x-ms-version" : "2018-03-28", + "Server" : "ECAcc (sed/E16F)", + "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", + "Last-Modified" : "Wed, 14 Apr 2021 00:08:03 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Access-Control-Allow-Headers" : "*", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "Vw1WdSQoTBOhmiB9XXUwsw==", + "Accept-Ranges" : "bytes", + "Access-Control-Expose-Headers" : "*", + "Etag" : "\"0x8D8FED95F570217\"", + "x-ms-request-id" : "8f0a7681-b01e-0021-1b52-ba22ba000000", "Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]", - "Age" : "437504", + "Age" : "67480", "Content-Type" : "application/json" }, "Exception" : null diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[3].json new file mode 100644 index 0000000000000..1988688b1b698 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[3].json @@ -0,0 +1,136 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "373d3fb2-3224-4231-82b9-88317026322b" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "117", + "Access-Control-Allow-Origin" : "*", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "301", + "Source-Age" : "3152", + "Date" : "Wed, 06 Oct 2021 20:20:38 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551639.640685,VS0,VE1", + "Accept-Ranges" : "bytes", + "X-Served-By" : "cache-sea4467-SEA", + "Vary" : "Authorization,Accept-Encoding", + "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT", + "X-Cache-Hits" : "1", + "Body" : "Moved Permanently.\n\n", + "X-Fastly-Request-ID" : "d4b04e5c26caad09bfafe6fc4a34fbb2f9bbd722", + "Content-Type" : "text/html; charset=utf-8", + "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json", + "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "fd2bb724-ce53-4876-82d5-dfa44781e212" + }, + "Response" : { + "content-length" : "2212", + "Access-Control-Allow-Origin" : "*", + "retry-after" : "0", + "StatusCode" : "200", + "Source-Age" : "16", + "X-Timer" : "S1633551639.657189,VS0,VE1", + "X-Frame-Options" : "deny", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4481-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "X-XSS-Protection" : "1; mode=block", + "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "956E:278C:249C9:34469:615DF8C6", + "X-Cache" : "HIT", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "Date" : "Wed, 06 Oct 2021 20:20:38 GMT", + "Via" : "1.1 varnish", + "Accept-Ranges" : "bytes", + "Cache-Control" : "max-age=300", + "ETag" : "\"7952e5f1274fe59fa4aa27c6ba55a1aebec0d5b2ac12f5c8124bbfb08eae4eee\"", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT", + "X-Cache-Hits" : "1", + "X-Fastly-Request-ID" : "5df4bd0e445a001660fc9bbc87a07e197269cd3b" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "7d8e24f6-1a2f-497e-a2b4-8476009e83b0" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "117", + "Access-Control-Allow-Origin" : "*", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "301", + "Source-Age" : "3152", + "Date" : "Wed, 06 Oct 2021 20:20:38 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551639.680088,VS0,VE0", + "Accept-Ranges" : "bytes", + "X-Served-By" : "cache-sea4476-SEA", + "Vary" : "Authorization,Accept-Encoding", + "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT", + "X-Cache-Hits" : "3", + "Body" : "Moved Permanently.\n\n", + "X-Fastly-Request-ID" : "6e6bca3cad481da68ff97ac490b38c49e575b967", + "Content-Type" : "text/html; charset=utf-8", + "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json", + "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0d61b93e-98bd-4a7a-9091-d05701c8a0f8" + }, + "Response" : { + "content-length" : "2212", + "Access-Control-Allow-Origin" : "*", + "retry-after" : "0", + "StatusCode" : "200", + "Source-Age" : "16", + "X-Timer" : "S1633551639.692640,VS0,VE1", + "X-Frame-Options" : "deny", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4479-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "X-XSS-Protection" : "1; mode=block", + "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "956E:278C:249C9:34469:615DF8C6", + "X-Cache" : "HIT", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "Date" : "Wed, 06 Oct 2021 20:20:38 GMT", + "Via" : "1.1 varnish", + "Accept-Ranges" : "bytes", + "Cache-Control" : "max-age=300", + "ETag" : "\"7952e5f1274fe59fa4aa27c6ba55a1aebec0d5b2ac12f5c8124bbfb08eae4eee\"", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT", + "X-Cache-Hits" : "1", + "X-Fastly-Request-ID" : "fab5c72ec9b38e981c9a9405ccd9db4ef5f0b69e" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[4].json new file mode 100644 index 0000000000000..ba5f37f8f8555 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsEnsureNoDuplicates[4].json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json index ffa602fc472c9..df0d661c890b7 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[1].json @@ -1,47 +1,80 @@ { "networkCallRecords" : [ { "Method" : "GET", - "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostatddd-1.expanded.json", + "Uri" : "https://REDACTED.azure.com/%2Fmetadata.json", "Headers" : { - "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)", - "x-ms-client-request-id" : "a8905328-6bf9-4a21-92bd-e78de3658d58" + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "ef345dbe-e307-4889-a2f4-5578b581d5f4" }, "Response" : { + "X-Cache" : "HIT", + "content-length" : "253", + "x-ms-version" : "2018-03-28", + "Server" : "ECAcc (sed/E179)", + "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", + "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Access-Control-Allow-Headers" : "*", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==", + "Accept-Ranges" : "bytes", + "Access-Control-Expose-Headers" : "*", + "Cache-Control" : "max-age=600", + "Etag" : "\"0x8D988F70ADF0EEF\"", + "x-ms-error-code" : "ConditionNotMet", + "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT", + "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000", + "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}", + "Age" : "15", + "Content-Type" : "application/json" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostatddd-1.expanded.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0d9db165-514f-4943-bc54-253613fa1327" + }, + "Response" : { + "content-length" : "321", "x-ms-version" : "2018-03-28", "Server" : "Windows-Azure-Web/1.0 Microsoft-HTTPAPI/2.0", "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", "retry-after" : "0", "StatusCode" : "404", "Access-Control-Allow-Headers" : "*", - "Date" : "Tue, 23 Mar 2021 22:20:07 GMT", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", "Access-Control-Expose-Headers" : "*", + "Vary" : "Origin", "x-ms-error-code" : "WebContentNotFound", - "Content-Length" : "321", - "x-ms-request-id" : "3c9fb664-c01e-004b-3232-20c175000000", - "Body" : "WebContentNotFound

The requested content does not exist.

  • HttpStatusCode: 404
  • ErrorCode: WebContentNotFound
  • RequestId : 3c9fb664-c01e-004b-3232-20c175000000
  • TimeStamp : 2021-03-23T22:20:07.2215660Z

", + "x-ms-request-id" : "c9d3efa3-e01e-00b8-2fef-bab6de000000", + "Body" : "WebContentNotFound

The requested content does not exist.

  • HttpStatusCode: 404
  • ErrorCode: WebContentNotFound
  • RequestId : c9d3efa3-e01e-00b8-2fef-bab6de000000
  • TimeStamp : 2021-10-06T20:20:38.0079901Z

", "Content-Type" : "text/html" }, "Exception" : null }, { "Method" : "GET", - "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostatddd-1.json", + "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostatddd-1.json", "Headers" : { - "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)", - "x-ms-client-request-id" : "e833bda3-456a-470f-862b-b11625f09186" + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "6a9fbf15-79fe-4873-9013-d457ed632988" }, "Response" : { + "content-length" : "321", "x-ms-version" : "2018-03-28", "Server" : "Windows-Azure-Web/1.0 Microsoft-HTTPAPI/2.0", "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", "retry-after" : "0", "StatusCode" : "404", "Access-Control-Allow-Headers" : "*", - "Date" : "Tue, 23 Mar 2021 22:20:06 GMT", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", "Access-Control-Expose-Headers" : "*", + "Vary" : "Origin", "x-ms-error-code" : "WebContentNotFound", - "Content-Length" : "321", - "x-ms-request-id" : "5b308299-601e-0051-0632-207f42000000", - "Body" : "WebContentNotFound

The requested content does not exist.

  • HttpStatusCode: 404
  • ErrorCode: WebContentNotFound
  • RequestId : 5b308299-601e-0051-0632-207f42000000
  • TimeStamp : 2021-03-23T22:20:07.3151755Z

", + "x-ms-request-id" : "93e6433d-b01e-000d-42ef-ba4790000000", + "Body" : "WebContentNotFound

The requested content does not exist.

  • HttpStatusCode: 404
  • ErrorCode: WebContentNotFound
  • RequestId : 93e6433d-b01e-000d-42ef-ba4790000000
  • TimeStamp : 2021-10-06T20:20:38.0458965Z

", "Content-Type" : "text/html" }, "Exception" : null diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[3].json new file mode 100644 index 0000000000000..4971f92c95294 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[3].json @@ -0,0 +1,68 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "c1df76ad-7678-4dfb-8ff5-37d956634207" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "117", + "Access-Control-Allow-Origin" : "*", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "301", + "Source-Age" : "3151", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551638.736753,VS0,VE1", + "Accept-Ranges" : "bytes", + "X-Served-By" : "cache-sea4481-SEA", + "Vary" : "Authorization,Accept-Encoding", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "Body" : "Moved Permanently.\n\n", + "X-Fastly-Request-ID" : "8e1f2b87ec661ad60631285a5fe0d96514e365d2", + "Content-Type" : "text/html; charset=utf-8", + "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json", + "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostatddd-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "fdd06ab2-74ce-4ffd-a880-919642f59d4d" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "14", + "Access-Control-Allow-Origin" : "*", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "404", + "Source-Age" : "15", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551638.793259,VS0,VE1", + "X-Frame-Options" : "deny", + "Accept-Ranges" : "bytes", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4481-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-XSS-Protection" : "1; mode=block", + "X-Cache-Hits" : "1", + "Body" : "404: Not Found", + "X-Fastly-Request-ID" : "4b3fa9f84ad37624375c7db2b6d442ad910de934", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "7C18:1911:33727:48D74:615E0506" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[4].json new file mode 100644 index 0000000000000..ba5f37f8f8555 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiDoesNotExist[4].json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json index 1c9f133670f38..1dcb383a60c15 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[1].json @@ -1,30 +1,60 @@ { "networkCallRecords" : [ { "Method" : "GET", - "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostat-1.expanded.json", + "Uri" : "https://REDACTED.azure.com/%2Fmetadata.json", "Headers" : { - "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)", - "x-ms-client-request-id" : "ce4f8dc5-3ea1-40b6-b04a-acdf4c035775" + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "00415d68-70ee-473f-b39d-ee1f248ed207" }, "Response" : { "X-Cache" : "HIT", + "content-length" : "253", "x-ms-version" : "2018-03-28", - "Server" : "ECAcc (sed/E120)", + "Server" : "ECAcc (sed/E179)", "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", - "Last-Modified" : "Tue, 15 Dec 2020 21:10:57 GMT", + "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT", "retry-after" : "0", "StatusCode" : "200", "Access-Control-Allow-Headers" : "*", - "Date" : "Tue, 23 Mar 2021 22:20:07 GMT", - "Content-MD5" : "pH51cS5+u5tWh2Krmys7qA==", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==", "Accept-Ranges" : "bytes", "Access-Control-Expose-Headers" : "*", - "Etag" : "\"0x8D8A13DEAC57DB3\"", + "Cache-Control" : "max-age=600", + "Etag" : "\"0x8D988F70ADF0EEF\"", "x-ms-error-code" : "ConditionNotMet", - "Content-Length" : "2651", - "x-ms-request-id" : "0552d4aa-d01e-006e-4479-1fd74c000000", + "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT", + "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000", + "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}", + "Age" : "15", + "Content-Type" : "application/json" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostat-1.expanded.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "60edc1e3-fa3e-4f82-a6e6-36844278b264" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "2651", + "x-ms-version" : "2018-03-28", + "Server" : "ECAcc (sed/E132)", + "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", + "Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Access-Control-Allow-Headers" : "*", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "pH51cS5+u5tWh2Krmys7qA==", + "Accept-Ranges" : "bytes", + "Access-Control-Expose-Headers" : "*", + "Etag" : "\"0x8D8FED94ECA13B6\"", + "x-ms-request-id" : "2e9bccae-e01e-0000-5a52-ba988b000000", "Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n }\n]", - "Age" : "79705", + "Age" : "67407", "Content-Type" : "application/json" }, "Exception" : null diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[3].json new file mode 100644 index 0000000000000..3855d02c7d648 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[3].json @@ -0,0 +1,70 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "4cf03b8b-a770-42bc-a551-fc3158b12654" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "117", + "Access-Control-Allow-Origin" : "*", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "301", + "Source-Age" : "3151", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551638.737897,VS0,VE1", + "Accept-Ranges" : "bytes", + "X-Served-By" : "cache-sea4476-SEA", + "Vary" : "Authorization,Accept-Encoding", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "Body" : "Moved Permanently.\n\n", + "X-Fastly-Request-ID" : "2d22f0a88716101930a7091385594781d8e367b3", + "Content-Type" : "text/html; charset=utf-8", + "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json", + "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostat-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "10ec23fa-79b5-4622-9fd0-552844bc945f" + }, + "Response" : { + "content-length" : "2469", + "Access-Control-Allow-Origin" : "*", + "retry-after" : "0", + "StatusCode" : "200", + "Source-Age" : "15", + "X-Timer" : "S1633551638.814445,VS0,VE1", + "X-Frame-Options" : "deny", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4479-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "X-XSS-Protection" : "1; mode=block", + "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "7A10:320C:3A12D:4AC16:615DF8C6", + "X-Cache" : "HIT", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "Accept-Ranges" : "bytes", + "Cache-Control" : "max-age=300", + "ETag" : "\"0d2c122754b690ebb4106d28683b3bc7be1dced98582291e46df6433d31e464d\"", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "X-Fastly-Request-ID" : "2c5f259ced15caef70ac53d71618fdfe8db3a8b3" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[4].json new file mode 100644 index 0000000000000..ba5f37f8f8555 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiNoDependencies[4].json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json index 90fb9b50ca99f..1b6744067777d 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[1].json @@ -1,30 +1,60 @@ { "networkCallRecords" : [ { "Method" : "GET", - "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Ftemperaturecontroller-1.expanded.json", + "Uri" : "https://REDACTED.azure.com/%2Fmetadata.json", "Headers" : { - "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)", - "x-ms-client-request-id" : "7b3aa5e5-c95b-46cd-b56a-52ba98c32fac" + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "572a992d-15f7-4a0c-920c-0775171cff1b" }, "Response" : { "X-Cache" : "HIT", + "content-length" : "253", "x-ms-version" : "2018-03-28", - "Server" : "ECAcc (sed/E17F)", + "Server" : "ECAcc (sed/E179)", "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", - "Last-Modified" : "Tue, 15 Dec 2020 21:10:57 GMT", + "Last-Modified" : "Wed, 06 Oct 2021 18:28:07 GMT", "retry-after" : "0", "StatusCode" : "200", "Access-Control-Allow-Headers" : "*", - "Date" : "Tue, 23 Mar 2021 22:20:07 GMT", - "Content-MD5" : "BnZpV2+7Z2t0sxAxOhmBdw==", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "x6Px49JuRM9EVDNUDRj0qA==", "Accept-Ranges" : "bytes", "Access-Control-Expose-Headers" : "*", - "Etag" : "\"0x8D8A13DEAC10FCC\"", + "Cache-Control" : "max-age=600", + "Etag" : "\"0x8D988F70ADF0EEF\"", "x-ms-error-code" : "ConditionNotMet", - "Content-Length" : "6751", - "x-ms-request-id" : "1b12122f-b01e-0044-7f29-1c486a000000", + "Expires" : "Wed, 06 Oct 2021 20:30:37 GMT", + "x-ms-request-id" : "4da670eb-801e-003a-50ef-bab78f000000", + "Body" : "{\n \"commitId\": \"16b04c45d99deb5438de3c5247a966e7596eaa44\",\n \"features\": {\n \"expanded\": true,\n \"index\": true\n },\n \"publishDateUtc\": \"2021-10-06T18:01:30.072670+00:00\",\n \"sourceRepo\": \"Azure/iot-plugandplay-models\",\n \"totalModelCount\": 19032\n}", + "Age" : "15", + "Content-Type" : "application/json" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Ftemperaturecontroller-1.expanded.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "761203d7-f656-4862-a5d5-160ef466ea91" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "6751", + "x-ms-version" : "2018-03-28", + "Server" : "ECAcc (sed/E17B)", + "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", + "Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT", + "retry-after" : "0", + "StatusCode" : "200", + "Access-Control-Allow-Headers" : "*", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Content-MD5" : "BnZpV2+7Z2t0sxAxOhmBdw==", + "Accept-Ranges" : "bytes", + "Access-Control-Expose-Headers" : "*", + "Etag" : "\"0x8D8FED94EBE03D1\"", + "x-ms-request-id" : "08c2b7cc-301e-0015-4552-baafa3000000", "Body" : "[\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:TemperatureController;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Temperature Controller\",\n \"description\": \"Device with two thermostats and remote reboot.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"DataSize\"\n ],\n \"name\": \"workingSet\",\n \"displayName\": \"Working Set\",\n \"description\": \"Current working set of the device memory in KiB.\",\n \"schema\": \"double\",\n \"unit\": \"kibibyte\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"serialNumber\",\n \"displayName\": \"Serial Number\",\n \"description\": \"Serial number of the device.\",\n \"schema\": \"string\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"reboot\",\n \"displayName\": \"Reboot\",\n \"description\": \"Reboots the device after waiting the number of seconds specified.\",\n \"request\": {\n \"name\": \"delay\",\n \"displayName\": \"Delay\",\n \"description\": \"Number of seconds to wait before rebooting the device.\",\n \"schema\": \"integer\"\n }\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat1\",\n \"displayName\": \"Thermostat One\",\n \"description\": \"Thermostat One of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat2\",\n \"displayName\": \"Thermostat Two\",\n \"description\": \"Thermostat Two of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"name\": \"deviceInformation\",\n \"displayName\": \"Device Information interface\",\n \"description\": \"Optional interface with basic device hardware information.\"\n }\n ]\n },\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n },\n {\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }\n]", - "Age" : "443781", + "Age" : "67407", "Content-Type" : "application/json" }, "Exception" : null diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[3].json new file mode 100644 index 0000000000000..74573950aa227 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[3].json @@ -0,0 +1,202 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "944945f9-28df-45ce-95d9-b9a4e0bb757a" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "117", + "Access-Control-Allow-Origin" : "*", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "301", + "Source-Age" : "3151", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551638.738065,VS0,VE1", + "Accept-Ranges" : "bytes", + "X-Served-By" : "cache-sea4425-SEA", + "Vary" : "Authorization,Accept-Encoding", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "Body" : "Moved Permanently.\n\n", + "X-Fastly-Request-ID" : "753a5ba57fcb35261a05e41c5c3c56376b90d51a", + "Content-Type" : "text/html; charset=utf-8", + "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json", + "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Ftemperaturecontroller-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "afd14528-37d5-43f5-b17e-bb71455ec7a1" + }, + "Response" : { + "content-length" : "1762", + "Access-Control-Allow-Origin" : "*", + "retry-after" : "0", + "StatusCode" : "200", + "Source-Age" : "15", + "X-Timer" : "S1633551638.790204,VS0,VE1", + "X-Frame-Options" : "deny", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4430-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "X-XSS-Protection" : "1; mode=block", + "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:TemperatureController;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Temperature Controller\",\n \"description\": \"Device with two thermostats and remote reboot.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"DataSize\"\n ],\n \"name\": \"workingSet\",\n \"displayName\": \"Working Set\",\n \"description\": \"Current working set of the device memory in KiB.\",\n \"schema\": \"double\",\n \"unit\": \"kibibyte\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"serialNumber\",\n \"displayName\": \"Serial Number\",\n \"description\": \"Serial number of the device.\",\n \"schema\": \"string\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"reboot\",\n \"displayName\": \"Reboot\",\n \"description\": \"Reboots the device after waiting the number of seconds specified.\",\n \"request\": {\n \"name\": \"delay\",\n \"displayName\": \"Delay\",\n \"description\": \"Number of seconds to wait before rebooting the device.\",\n \"schema\": \"integer\"\n }\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat1\",\n \"displayName\": \"Thermostat One\",\n \"description\": \"Thermostat One of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:com:example:Thermostat;1\",\n \"name\": \"thermostat2\",\n \"displayName\": \"Thermostat Two\",\n \"description\": \"Thermostat Two of Two.\"\n },\n {\n \"@type\": \"Component\",\n \"schema\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"name\": \"deviceInformation\",\n \"displayName\": \"Device Information interface\",\n \"description\": \"Optional interface with basic device hardware information.\"\n }\n ]\n}", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "3088:6400:89E1:16994:615DF8C6", + "X-Cache" : "HIT", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "Accept-Ranges" : "bytes", + "Cache-Control" : "max-age=300", + "ETag" : "\"276d790fcfc6c0c7637965a33d2bf9cea2a8583f385ee2d1c5d16823814b3094\"", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "X-Fastly-Request-ID" : "fbebc8be9c92c71f316deaf54b7377c57ffa3158" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "63cb65f7-5200-4e35-9a7e-427d41c863dd" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "117", + "Access-Control-Allow-Origin" : "*", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "301", + "Source-Age" : "3151", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551638.806824,VS0,VE0", + "Accept-Ranges" : "bytes", + "X-Served-By" : "cache-sea4476-SEA", + "Vary" : "Authorization,Accept-Encoding", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "2", + "Body" : "Moved Permanently.\n\n", + "X-Fastly-Request-ID" : "5493b55c016061f5c2732324e8a654246408f1e3", + "Content-Type" : "text/html; charset=utf-8", + "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json", + "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostat-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "572b80d5-cff5-49c6-bfb7-7432b1155f1c" + }, + "Response" : { + "content-length" : "2469", + "Access-Control-Allow-Origin" : "*", + "retry-after" : "0", + "StatusCode" : "200", + "Source-Age" : "15", + "X-Timer" : "S1633551638.827640,VS0,VE1", + "X-Frame-Options" : "deny", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4425-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "X-XSS-Protection" : "1; mode=block", + "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "7A10:320C:3A12D:4AC16:615DF8C6", + "X-Cache" : "HIT", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "Accept-Ranges" : "bytes", + "Cache-Control" : "max-age=300", + "ETag" : "\"0d2c122754b690ebb4106d28683b3bc7be1dced98582291e46df6433d31e464d\"", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "X-Fastly-Request-ID" : "c293bc980713d9739478bdfc73afb537758f0ba5" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/%2FAzure%2Fiot-plugandplay-models%2Fmain%2Fmetadata.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "73b90be1-2ca8-4552-ba51-b5a0ed23d254" + }, + "Response" : { + "X-Cache" : "HIT", + "content-length" : "117", + "Access-Control-Allow-Origin" : "*", + "Connection" : "keep-alive", + "retry-after" : "0", + "StatusCode" : "301", + "Source-Age" : "3151", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "X-Timer" : "S1633551638.839463,VS0,VE0", + "Accept-Ranges" : "bytes", + "X-Served-By" : "cache-sea4430-SEA", + "Vary" : "Authorization,Accept-Encoding", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "Body" : "Moved Permanently.\n\n", + "X-Fastly-Request-ID" : "c70431723262afd1fdf226a53fe090cb47db2fa8", + "Content-Type" : "text/html; charset=utf-8", + "Location" : "/Azure/iot-plugandplay-models/main/Azure/iot-plugandplay-models/main/metadata.json", + "X-GitHub-Request-Id" : "3658:1B57:376C8:48218:615DF8C6" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fazure%2Fdevicemanagement%2Fdeviceinformation-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0d61b93e-98bd-4a7a-9091-d05701c8a0f8" + }, + "Response" : { + "content-length" : "2212", + "Access-Control-Allow-Origin" : "*", + "retry-after" : "0", + "StatusCode" : "200", + "Source-Age" : "16", + "X-Timer" : "S1633551639.692640,VS0,VE1", + "X-Frame-Options" : "deny", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4479-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "X-XSS-Protection" : "1; mode=block", + "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:azure:DeviceManagement:DeviceInformation;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Device Information\",\n \"contents\": [\n {\n \"@type\": \"Property\",\n \"name\": \"manufacturer\",\n \"displayName\": \"Manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Company name of the device manufacturer. This could be the same as the name of the original equipment manufacturer (OEM). Ex. Contoso.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"model\",\n \"displayName\": \"Device model\",\n \"schema\": \"string\",\n \"description\": \"Device model name or ID. Ex. Surface Book 2.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"swVersion\",\n \"displayName\": \"Software version\",\n \"schema\": \"string\",\n \"description\": \"Version of the software on your device. This could be the version of your firmware. Ex. 1.3.45\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"osName\",\n \"displayName\": \"Operating system name\",\n \"schema\": \"string\",\n \"description\": \"Name of the operating system on the device. Ex. Windows 10 IoT Core.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorArchitecture\",\n \"displayName\": \"Processor architecture\",\n \"schema\": \"string\",\n \"description\": \"Architecture of the processor on the device. Ex. x64 or ARM.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"processorManufacturer\",\n \"displayName\": \"Processor manufacturer\",\n \"schema\": \"string\",\n \"description\": \"Name of the manufacturer of the processor on the device. Ex. Intel.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalStorage\",\n \"displayName\": \"Total storage\",\n \"schema\": \"double\",\n \"description\": \"Total available storage on the device in kilobytes. Ex. 2048000 kilobytes.\"\n },\n {\n \"@type\": \"Property\",\n \"name\": \"totalMemory\",\n \"displayName\": \"Total memory\",\n \"schema\": \"double\",\n \"description\": \"Total available memory on the device in kilobytes. Ex. 256000 kilobytes.\"\n }\n ]\n }", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "956E:278C:249C9:34469:615DF8C6", + "X-Cache" : "HIT", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "Date" : "Wed, 06 Oct 2021 20:20:38 GMT", + "Via" : "1.1 varnish", + "Accept-Ranges" : "bytes", + "Cache-Control" : "max-age=300", + "ETag" : "\"7952e5f1274fe59fa4aa27c6ba55a1aebec0d5b2ac12f5c8124bbfb08eae4eee\"", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:38 GMT", + "X-Cache-Hits" : "1", + "X-Fastly-Request-ID" : "fab5c72ec9b38e981c9a9405ccd9db4ef5f0b69e" + }, + "Exception" : null + } ], + "variables" : [ ] +} diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[4].json new file mode 100644 index 0000000000000..ba5f37f8f8555 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDependencies[4].json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json index 54051cf4b7951..1f05d86e39471 100644 --- a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[1].json @@ -1,30 +1,30 @@ { "networkCallRecords" : [ { "Method" : "GET", - "Uri" : "https://REDACTED.azure.com/%2Fdtmi%2Fcom%2Fexample%2Fthermostat-1.json", + "Uri" : "https://REDACTED.azure.com/dtmi%2Fcom%2Fexample%2Fthermostat-1.json", "Headers" : { - "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.1.0-beta.1 (11.0.7; Windows 10; 10.0)", - "x-ms-client-request-id" : "537a41a9-a508-4e4a-8390-6399bb3ffb01" + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "1430d25e-3dd9-430d-b1b7-7ea24f5fd6a5" }, "Response" : { "X-Cache" : "HIT", + "content-length" : "2469", "x-ms-version" : "2018-03-28", - "Server" : "ECAcc (sed/E107)", + "Server" : "ECAcc (sed/E154)", "Access-Control-Allow-Methods" : "GET, HEAD, OPTIONS", - "Last-Modified" : "Tue, 15 Dec 2020 21:10:57 GMT", + "Last-Modified" : "Wed, 14 Apr 2021 00:07:35 GMT", "retry-after" : "0", "StatusCode" : "200", "Access-Control-Allow-Headers" : "*", - "Date" : "Tue, 23 Mar 2021 22:20:07 GMT", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", "Content-MD5" : "U0VZgOgpfb6bwvG5UDVZuw==", "Accept-Ranges" : "bytes", "Access-Control-Expose-Headers" : "*", - "Etag" : "\"0x8D8A13DEABC53BA\"", + "Etag" : "\"0x8D8FED94ED5FC94\"", "x-ms-error-code" : "ConditionNotMet", - "Content-Length" : "2469", - "x-ms-request-id" : "3e2ce5fe-301e-0060-0838-1c7551000000", + "x-ms-request-id" : "8b667ceb-b01e-00a5-2757-b6d9e7000000", "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}", - "Age" : "437504", + "Age" : "505072", "Content-Type" : "application/json" }, "Exception" : null diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[3].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[3].json new file mode 100644 index 0000000000000..011ac367502b4 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[3].json @@ -0,0 +1,40 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "https://REDACTED.githubusercontent.com/Azure/iot-plugandplay-models/main/dtmi%2Fcom%2Fexample%2Fthermostat-1.json", + "Headers" : { + "User-Agent" : "azsdk-java-azure-iot-modelsrepository/1.0.0-beta.2 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "9e54d0ce-4794-472b-bcb3-6f776c62d69c" + }, + "Response" : { + "content-length" : "2469", + "Access-Control-Allow-Origin" : "*", + "retry-after" : "0", + "StatusCode" : "200", + "Source-Age" : "15", + "X-Timer" : "S1633551638.735210,VS0,VE1", + "X-Frame-Options" : "deny", + "Strict-Transport-Security" : "max-age=31536000", + "X-Served-By" : "cache-sea4430-SEA", + "Content-Security-Policy" : "default-src 'none'; style-src 'unsafe-inline'; sandbox", + "X-XSS-Protection" : "1; mode=block", + "Body" : "{\n \"@context\": \"dtmi:dtdl:context;2\",\n \"@id\": \"dtmi:com:example:Thermostat;1\",\n \"@type\": \"Interface\",\n \"displayName\": \"Thermostat\",\n \"description\": \"Reports current temperature and provides desired temperature control.\",\n \"contents\": [\n {\n \"@type\": [\n \"Telemetry\",\n \"Temperature\"\n ],\n \"name\": \"temperature\",\n \"displayName\": \"Temperature\",\n \"description\": \"Temperature in degrees Celsius.\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\"\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"targetTemperature\",\n \"schema\": \"double\",\n \"displayName\": \"Target Temperature\",\n \"description\": \"Allows to remotely specify the desired target temperature.\",\n \"unit\": \"degreeCelsius\",\n \"writable\": true\n },\n {\n \"@type\": [\n \"Property\",\n \"Temperature\"\n ],\n \"name\": \"maxTempSinceLastReboot\",\n \"schema\": \"double\",\n \"unit\": \"degreeCelsius\",\n \"displayName\": \"Max temperature since last reboot.\",\n \"description\": \"Returns the max temperature since last device reboot.\"\n },\n {\n \"@type\": \"Command\",\n \"name\": \"getMaxMinReport\",\n \"displayName\": \"Get Max-Min report.\",\n \"description\": \"This command returns the max, min and average temperature from the specified time to the current time.\",\n \"request\": {\n \"name\": \"since\",\n \"displayName\": \"Since\",\n \"description\": \"Period to return the max-min report.\",\n \"schema\": \"dateTime\"\n },\n \"response\": {\n \"name\": \"tempReport\",\n \"displayName\": \"Temperature Report\",\n \"schema\": {\n \"@type\": \"Object\",\n \"fields\": [\n {\n \"name\": \"maxTemp\",\n \"displayName\": \"Max temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"minTemp\",\n \"displayName\": \"Min temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"avgTemp\",\n \"displayName\": \"Average Temperature\",\n \"schema\": \"double\"\n },\n {\n \"name\": \"startTime\",\n \"displayName\": \"Start Time\",\n \"schema\": \"dateTime\"\n },\n {\n \"name\": \"endTime\",\n \"displayName\": \"End Time\",\n \"schema\": \"dateTime\"\n }\n ]\n }\n }\n }\n ]\n}", + "Content-Type" : "text/plain; charset=utf-8", + "X-GitHub-Request-Id" : "7A10:320C:3A12D:4AC16:615DF8C6", + "X-Cache" : "HIT", + "X-Content-Type-Options" : "nosniff", + "Connection" : "keep-alive", + "Date" : "Wed, 06 Oct 2021 20:20:37 GMT", + "Via" : "1.1 varnish", + "Accept-Ranges" : "bytes", + "Cache-Control" : "max-age=300", + "ETag" : "\"0d2c122754b690ebb4106d28683b3bc7be1dced98582291e46df6433d31e464d\"", + "Vary" : "Authorization,Accept-Encoding,Origin", + "Expires" : "Wed, 06 Oct 2021 20:25:37 GMT", + "X-Cache-Hits" : "1", + "X-Fastly-Request-ID" : "7343f212515edee8dfd161a8a65c274ab6988010" + }, + "Exception" : null + } ], + "variables" : [ ] +} \ No newline at end of file diff --git a/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[4].json b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[4].json new file mode 100644 index 0000000000000..ba5f37f8f8555 --- /dev/null +++ b/sdk/modelsrepository/azure-iot-modelsrepository/src/test/resources/session-records/ModelRepositoryIntegrationTests.getModelsSingleDtmiWithDepsDisableDependencyResolution[4].json @@ -0,0 +1,4 @@ +{ + "networkCallRecords" : [ ], + "variables" : [ ] +} \ No newline at end of file