/// <summary> /// Parses and checks the given JSON object to see if any armTemplateParameters were added or removed. /// If parameters were added then they are created in the db along with a join entry in the armTemplateArmTemplateParameters table. /// If parameters were removed then the join entry in the armTemplateArmTemplateParameters table is removed. /// </summary> /// <param name="offer">The name of the offer the parameters belong to</param> /// <param name="armTemplateJSON">The JSON object to parse.</param> /// <param name="armTemplateId">The ID of the armTemplate.</param> /// <returns></returns> private async Task UpdateArmTemplateParameters(Offer offer, object armTemplateJSON, long armTemplateId) { List <KeyValuePair <string, string> > incompleteParams = ARMTemplateHelper.GetArmTemplateParameters(armTemplateJSON.ToString()); List <ArmTemplateArmTemplateParameter> joinEntries = await _armTemplateArmTemplateParameterService.GetAllJoinEntries(armTemplateId); Dictionary <string, ArmTemplateParameter> paramsDb = new Dictionary <string, ArmTemplateParameter>(); HashSet <string> usedParamNames = new HashSet <string>(); // Populate paramsDb so that it maps the ArmTemplateParameter name to the ArmTemplateParameter object foreach (ArmTemplateArmTemplateParameter entry in joinEntries) { ArmTemplateParameter armTemplateParameter = await _context.ArmTemplateParameters.FindAsync(entry.ArmTemplateParameterId); if (!paramsDb.ContainsKey(armTemplateParameter.Name)) { paramsDb.Add(armTemplateParameter.Name, armTemplateParameter); } } foreach (KeyValuePair <string, string> incompleteParam in incompleteParams) { // Check if a param with the same name as the incompleteParam already exists if (!paramsDb.ContainsKey(incompleteParam.Key)) { ArmTemplateParameter armParameter = new ArmTemplateParameter { OfferId = offer.Id, Name = incompleteParam.Key, Type = incompleteParam.Value, // TODO: do we need to indicate an incomplete parameter? Value = string.Empty }; // A param with the same name as the incompleteParam does not exist, so create it await _armTemplateParameterService.CreateAsync(offer.OfferName, armTemplateId, armParameter); } // Keep track of all the new parameters we are using in usedParamNames if (!usedParamNames.Contains(incompleteParam.Key)) { usedParamNames.Add(incompleteParam.Key); } } foreach (KeyValuePair <string, ArmTemplateParameter> paramDb in paramsDb) { // Check if there is a param in the db that we are no longer using if (!usedParamNames.Contains(paramDb.Key)) { ArmTemplateArmTemplateParameter armTemplateArmTemplateParameter = await _context.ArmTemplateArmTemplateParameters.FindAsync(armTemplateId, paramDb.Value.Id); // Remove the join entry for any unused params _context.ArmTemplateArmTemplateParameters.Remove(armTemplateArmTemplateParameter); await _context._SaveChangesAsync(); } } }
public void Constructor_TypeInArmValueTypes_SetPropertiesAsExpected() { var actual = new ArmTemplateParameter(paramName, paramValue, "bool"); var expectedReferencePattern = @"parameters\([""']{1}testParam[""']{1}\)"; Assert.Equal(paramName, actual.Name); Assert.Equal(paramValue, actual.Value); Assert.Equal("bool", actual.Type); Assert.Equal(expectedReferencePattern, actual.ReferencePattern.ToString()); }
/// <summary> /// Parse the ARM template to get the parameter names and build an object containing the parameter names and values /// </summary> /// <param name="offer"></param> /// <param name="plan"></param> /// <param name="subscriptionAction"></param> /// <returns>An object containing the parameter names and values</returns> public async Task <Dictionary <string, object> > GetTemplateParameters( Offer offer, Plan plan, FulfillmentAction subscriptionAction ) { ArmTemplate template = null; switch (subscriptionAction) { case FulfillmentAction.Activate: template = await _lunaClient.GetArmTemplate(offer.OfferName, plan.SubscribeArmTemplateName); break; case FulfillmentAction.Update: template = await _lunaClient.GetArmTemplate(offer.OfferName, plan.SubscribeArmTemplateName); break; case FulfillmentAction.Unsubscribe: template = await _lunaClient.GetArmTemplate(offer.OfferName, plan.UnsubscribeArmTemplateName); break; default: throw new InvalidEnumArgumentException(); } string templateContent = await _storage.DownloadToTextAsync(template.TemplateFilePath); var parameters = ARMTemplateHelper.GetArmTemplateParameters(templateContent); var parameterList = new Dictionary <string, object>(); foreach (var parameter in parameters) { ArmTemplateParameter atp = await _lunaClient.GetArmTemplateParameter(offer.OfferName, parameter.Key); parameterList.Add( atp.Name, new { Value = atp.Value } ); } return(parameterList); }
/// <summary> /// Parses the given JSON object for ArmTemplateParameters then creates them in the db. /// The join entry is also created in the armTemplateArmTemplateParameters table. /// </summary> /// <param name="offer">The name of the offer the parameters belong to.</param> /// <param name="armTemplateJSON">The JSON to parse.</param> /// <param name="armTemplateId">The ID of the armTemplate.</param> /// <returns></returns> private async Task CreateArmTemplateParameters(Offer offer, object armTemplateJSON, long armTemplateId) { var parameters = ARMTemplateHelper.GetArmTemplateParameters(armTemplateJSON.ToString()); foreach (var param in parameters) { ArmTemplateParameter armParameter = new ArmTemplateParameter { OfferId = offer.Id, Name = param.Key, Type = param.Value, // TODO: do we need to indicate an incomplete parameter? Value = string.Empty }; await _armTemplateParameterService.CreateAsync(offer.OfferName, armTemplateId, armParameter); } }
/// <summary> /// Creates an armTemplateParameter object within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="armTemplateId">The id of the armTemplate that the parameter is associated with.</param> /// <param name="armTemplateParameter">The armTemplateParameter to create.</param> /// <returns>The created armTemplateParameter.</returns> public async Task <ArmTemplateParameter> CreateAsync(string offerName, long armTemplateId, ArmTemplateParameter armTemplateParameter) { if (armTemplateParameter is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(ArmTemplateParameter).Name), UserErrorCode.PayloadNotProvided); } if (ExpressionEvaluationUtils.ReservedParameterNames.Contains(armTemplateParameter.Name)) { _logger.LogInformation($"ARM template {armTemplateId} is referencing system parameter {armTemplateParameter.Name}."); return(armTemplateParameter); //throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(ArmTemplateParameter).Name, // armTemplateParameter.Name, offerName: offerName)); } Offer offer = await _offerService.GetAsync(offerName); // Check if the ArmTemplateParameter already exists if (await ExistsAsync(offerName, armTemplateParameter.Name)) { // Just create a new join entry to keep track of the fact that this ArmTempate is using this parameter ArmTemplateParameter armTemplateParameterDb = await GetAsync(offerName, armTemplateParameter.Name); await _armTemplateArmTemplateParameterService.CreateJoinEntryAsync(armTemplateId, armTemplateParameterDb.Id); return(armTemplateParameterDb); } armTemplateParameter.OfferId = offer.Id; _context.ArmTemplateParameters.Add(armTemplateParameter); await _context._SaveChangesAsync(); await _armTemplateArmTemplateParameterService.CreateJoinEntryAsync(armTemplateId, armTemplateParameter.Id); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(ArmTemplateParameter).Name, armTemplateParameter.Name, offerName: offerName)); return(armTemplateParameter); }
/// <summary> /// Updates an ArmTemplateParameter within an offer by name. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="parameterName">The name of the ArmTemplateParameter to update.</param> /// <param name="armTemplateParameter">The updated ArmTemplateParameter object.</param> /// <returns>The updated ArmTemplateParameter object.</returns> public async Task <ArmTemplateParameter> UpdateAsync(string offerName, string parameterName, ArmTemplateParameter armTemplateParameter) { if (armTemplateParameter is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(ArmTemplateParameter).Name), UserErrorCode.PayloadNotProvided); } _logger.LogInformation(LoggingUtils.ComposeUpdateResourceMessage(typeof(ArmTemplateParameter).Name, armTemplateParameter.Name, offerName: offerName, payload: JsonSerializer.Serialize(armTemplateParameter))); Offer offer = await _offerService.GetAsync(offerName); ArmTemplateParameter armTemplateParameterDb = await GetAsync(offerName, parameterName); armTemplateParameterDb.Copy(armTemplateParameter); armTemplateParameterDb.OfferId = offer.Id; _context.ArmTemplateParameters.Update(armTemplateParameterDb); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceUpdatedMessage(typeof(ArmTemplateParameter).Name, armTemplateParameter.Name, offerName: offerName)); return(armTemplateParameterDb); }
public async Task <ActionResult> UpdateAsync(string offerName, string name, [FromBody] ArmTemplateParameter armTemplateParameter) { AADAuthHelper.VerifyUserAccess(this.HttpContext, _logger, true); if (armTemplateParameter == null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(ArmTemplateParameter).Name), UserErrorCode.PayloadNotProvided); } if (!name.Equals(armTemplateParameter.Name)) { throw new LunaBadRequestUserException(LoggingUtils.ComposeNameMismatchErrorMessage(typeof(ArmTemplateParameter).Name), UserErrorCode.NameMismatch); } _logger.LogInformation(LoggingUtils.ComposeUpdateResourceMessage(typeof(ArmTemplateParameter).Name, name, JsonSerializer.Serialize(armTemplateParameter))); await _armTemplateParameterService.UpdateAsync(offerName, name, armTemplateParameter); return(Ok(armTemplateParameter)); }
/// <summary> /// Uploads the given armTemplate as a JSON file in blob storage and records the URI to the /// created resrouce in the db. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="templateName">The name of the ARM template.</param> /// <param name="armTemplateJSON">The ARM Template's raw JSON data.</param> /// <returns>The created armTemplate db record.</returns> public async Task <ArmTemplate> CreateAsync(string offerName, string templateName, object armTemplateJSON) { if (armTemplateJSON is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(ArmTemplate).Name), UserErrorCode.PayloadNotProvided); } // Check that the offer does not already have an armTemplate with the same templateName if (await ExistsAsync(offerName, templateName)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(ArmTemplate).Name, templateName, offerName: offerName)); } // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(offerName); // Get the container name associated with the offer var containerName = offer.ContainerName.ToString(); // Upload the armTemplateJSON as a file in blob storage and get the URL to the created resource var url = await uploadToBlobStorageAsync(containerName, GetArmTemplateFileName(templateName), armTemplateJSON.ToString()); _logger.LogInformation($"Arm template {templateName} in offer {offerName} is uploaded to {url}."); // Create the armTemplate to store in db ArmTemplate armTemplate = new ArmTemplate { OfferId = offer.Id, TemplateName = templateName, TemplateFilePath = url }; // Add armTemplate to db _context.ArmTemplates.Add(armTemplate); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(ArmTemplate).Name, templateName, offerName: offerName)); if (!await _armTemplateParameterService.ExistsAsync(offerName, "resourceGroupLocation")) { // Add parameter for resourceGroupLocation ArmTemplateParameter armParameter = new ArmTemplateParameter { OfferId = offer.Id, Name = "resourceGroupLocation", Type = "string", // TODO: do we need to indicate an incomplete parameter? Value = string.Empty }; await _armTemplateParameterService.CreateAsync(offerName, armTemplate.Id, armParameter); } if (!await _armTemplateParameterService.ExistsAsync(offerName, "entryPointUrl")) { // Add parameter for entryPointLink ArmTemplateParameter armParameter = new ArmTemplateParameter { OfferId = offer.Id, Name = "entryPointUrl", Type = "string", // TODO: do we need to indicate an incomplete parameter? Value = string.Empty }; await _armTemplateParameterService.CreateAsync(offerName, armTemplate.Id, armParameter); } // Add arm template parameters await CreateArmTemplateParameters(offer, armTemplateJSON, armTemplate.Id); return(armTemplate); }