// Verifies if a tracked resource has a corresponding PATCH operation
        public override IEnumerable <ValidationMessage> GetValidationMessages(Dictionary <string, Schema> definitions, RuleContext context)
        {
            ServiceDefinition serviceDefinition = (ServiceDefinition)context.Root;
            // enumerate all the PATCH operations
            IEnumerable <Operation> patchOperations = ValidationUtilities.GetOperationsByRequestMethod("patch", serviceDefinition);

            foreach (var op in patchOperations)
            {
                var reqModels = op.Parameters.Where(p => p.In == ParameterLocation.Body).Select(p => p.Schema?.Reference?.StripDefinitionPath()).Where(p => !string.IsNullOrEmpty(p));
                foreach (var reqModel in reqModels)
                {
                    // select all models that have properties set to required
                    var reqProps = ValidationUtilities.EnumerateRequiredProperties(reqModel, definitions);

                    // select all models that have properties with default values
                    var defValProps = ValidationUtilities.EnumerateDefaultValuedProperties(reqModel, definitions);

                    var modelHierarchy = ValidationUtilities.EnumerateModelHierarchy(reqModel, definitions);

                    foreach (var reqProp in reqProps)
                    {
                        var modelContainingReqProp = modelHierarchy.First(model => definitions[model].Required?.Contains(reqProp) == true);
                        yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty(modelContainingReqProp).AppendProperty("required")), this, "required", op.OperationId, modelContainingReqProp, reqProp));
                    }

                    foreach (var defValProp in defValProps)
                    {
                        var modelContainingDefValProp = modelHierarchy.First(model => definitions[model].Properties?.Contains(defValProp) == true);
                        yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty(modelContainingDefValProp).AppendProperty("properties").AppendProperty(defValProp.Key)), this, "default-valued", op.OperationId, modelContainingDefValProp, defValProp.Key));
                    }
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Verifies whether the location property for a tracked resource has the x-ms-mutability extension set correctly
        /// </summary>
        /// <param name="definitions"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override IEnumerable <ValidationMessage> GetValidationMessages(Dictionary <string, Schema> definitions, RuleContext context)
        {
            var trackedResources = context.TrackedResourceModels;

            foreach (var resource in trackedResources)
            {
                var modelHierarchy         = ValidationUtilities.EnumerateModelHierarchy(resource, definitions);
                var modelsWithLocationProp = modelHierarchy.Where(model => (definitions[model].Required?.Contains("location") == true) &&
                                                                  (definitions[model].Properties?.ContainsKey("location") == true));
                if (modelsWithLocationProp.Any())
                {
                    var modelWithLocationProp = modelsWithLocationProp.First();
                    if (definitions[modelWithLocationProp].Properties["location"].Extensions?.ContainsKey("x-ms-mutability") != true)
                    {
                        yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty("properties").AppendProperty("location")), this, modelWithLocationProp));
                    }
                    else
                    {
                        var jObject = JsonConvert.DeserializeObject <object[]>(definitions[modelWithLocationProp].Properties["location"].Extensions["x-ms-mutability"].ToString());
                        // make sure jObject and the expected mutability properties have exact same elements
                        if (jObject.Except(LocationPropertyMutability).Any() || LocationPropertyMutability.Except(jObject).Any())
                        {
                            yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty("properties").AppendProperty("location").AppendProperty("x-ms-mutability")), this, resource));
                        }
                    }
                }
            }
        }
Esempio n. 3
0
        // Verifies if a tracked resource has a corresponding PATCH operation
        public override IEnumerable <ValidationMessage> GetValidationMessages(Dictionary <string, Dictionary <string, Operation> > paths, RuleContext context)
        {
            var serviceDefinition = context.Root;
            var ops           = ValidationUtilities.GetOperationsByRequestMethod("put", serviceDefinition);
            var putRespModels = ops.Select(op => (op.Responses?.ContainsKey("200") != true) ? null : op.Responses["200"].Schema?.Reference?.StripDefinitionPath());

            putRespModels = putRespModels.Where(modelName => !string.IsNullOrEmpty(modelName));
            var xmsResModels    = ValidationUtilities.GetXmsAzureResourceModels(serviceDefinition.Definitions);
            var violatingModels = putRespModels.Where(respModel => !ValidationUtilities.EnumerateModelHierarchy(respModel, serviceDefinition.Definitions).Intersect(xmsResModels).Any());

            foreach (var model in violatingModels)
            {
                var violatingOp     = ops.Where(op => (op.Responses?.ContainsKey("200") == true) && op.Responses["200"]?.Schema?.Reference?.StripDefinitionPath() == model).First();
                var violatingPath   = ValidationUtilities.GetOperationIdPath(violatingOp.OperationId, paths);
                var violatingOpVerb = ValidationUtilities.GetOperationIdVerb(violatingOp.OperationId, violatingPath);
                yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty(violatingPath.Key).AppendProperty(violatingOpVerb)), this, violatingOp.OperationId, model));
            }
        }