/// <summary> /// Creates a plan within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="plan">The plan to create.</param> /// <returns>The created plan.</returns> public async Task <Plan> CreateAsync(string offerName, Plan plan) { if (plan is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(Plan).Name), UserErrorCode.PayloadNotProvided); } // Check that the offer does not already have an plan with the same planUniqueName if (await ExistsAsync(offerName, plan.PlanName)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(Plan).Name, plan.PlanName, offerName: offerName)); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(Plan).Name, plan.PlanName, offerName: offerName, payload: JsonSerializer.Serialize(plan))); // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(offerName); // Set the FK to offer plan.OfferId = offer.Id; plan = await SetArmTemplateAndWebhookIds(offerName, plan); // Add plan to db _context.Plans.Add(plan); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(Plan).Name, plan.PlanName, offerName: offerName)); return(plan); }
/// <summary> /// Creates a webhook within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="webhook">The webhook to create.</param> /// <returns>The created webhook.</returns> public async Task <Webhook> CreateAsync(string offerName, Webhook webhook) { if (webhook is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(Webhook).Name), UserErrorCode.PayloadNotProvided); } // Check that the offer does not already have a webhook with the same webhookName if (await ExistsAsync(offerName, webhook.WebhookName)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(Webhook).Name, webhook.WebhookName, offerName: offerName)); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(Webhook).Name, webhook.WebhookName, offerName: offerName, payload: JsonSerializer.Serialize(webhook))); // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(offerName); // Set the FK to offer webhook.OfferId = offer.Id; // Add webhook to db _context.Webhooks.Add(webhook); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(Webhook).Name, webhook.WebhookName, offerName: offerName)); await CreateWebhookParameters(offerName, webhook); return(webhook); }
/// <summary> /// Creates an aadSecretTmp object within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="aadSecretTmp">The aadSecretTmp object to create.</param> /// <returns>The created aadSecretTmp object.</returns> public async Task <AadSecretTmp> CreateAsync(string offerName, AadSecretTmp aadSecretTmp) { if (aadSecretTmp is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(AadSecretTmp).Name), UserErrorCode.PayloadNotProvided); } // Check that the offer does not already have an aadSecretTmp with the same name if (await ExistsAsync(offerName, aadSecretTmp.Name)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(AadSecretTmp).Name, aadSecretTmp.Name, offerName: offerName)); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(AadSecretTmp).Name, aadSecretTmp.Name, offerName: offerName, payload: JsonSerializer.Serialize(aadSecretTmp))); // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(offerName); // Set the FK to offer aadSecretTmp.OfferId = offer.Id; // Add aadSecretTmp to db _context.AadSecretTmps.Add(aadSecretTmp); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(AadSecretTmp).Name, aadSecretTmp.Name, offerName: offerName)); return(aadSecretTmp); }
/// <summary> /// Creates a restrictedUser within a plan within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="planUniqueName">The name of the plan.</param> /// <param name="restrictedUser">The restrictedUser to create.</param> /// <returns>The created restrictedUser.</returns> public async Task <RestrictedUser> CreateAsync(string offerName, string planUniqueName, RestrictedUser restrictedUser) { if (restrictedUser is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(RestrictedUser).Name), UserErrorCode.PayloadNotProvided); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(RestrictedUser).Name, restrictedUser.TenantId.ToString(), offerName: offerName, planName: planUniqueName, payload: JsonSerializer.Serialize(restrictedUser))); // Get the plan associated with the offerName and planUniqueName provided var plan = await _planService.GetAsync(offerName, planUniqueName); // Set the FK to plan restrictedUser.PlanId = plan.Id; // Reset the PK (should not be modified in request) restrictedUser.Id = 0; // Add restrictedUser to db _context.RestrictedUsers.Add(restrictedUser); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(RestrictedUser).Name, restrictedUser.TenantId.ToString(), offerName: offerName, planName: planUniqueName)); return(restrictedUser); }
/// <summary> /// Creates a customMeter. /// </summary> /// <param name="offerName">The offer name of the customMeter.</param> /// <param name="meterName">The name of the customMeter.</param> /// <param name="customMeter">The customMeter to create.</param> /// <returns>The created customMeter.</returns> public async Task <CustomMeter> CreateAsync(string offerName, string meterName, CustomMeter customMeter) { if (customMeter is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(CustomMeter).Name), UserErrorCode.PayloadNotProvided); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(CustomMeter).Name, customMeter.MeterName, offerName: offerName, payload: JsonSerializer.Serialize(customMeter))); // Check that an customMeter with the same name does not already exist if (await ExistsAsync(offerName, meterName)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(CustomMeter).Name, customMeter.MeterName, offerName: offerName)); } var offer = await _offerService.GetAsync(offerName); var connector = await _telemetryDataconnectorService.GetAsync(customMeter.TelemetryDataConnectorName); customMeter.TelemetryDataConnectorId = connector.Id; customMeter.OfferId = offer.Id; using (var transaction = await _context.BeginTransactionAsync()) { // Not using subscriptionService here to avoid circular reference List <Subscription> subscriptionList = _context.Subscriptions.Where(s => s.OfferId == offer.Id && (s.Status == FulfillmentState.Subscribed.ToString() || s.Status == FulfillmentState.Suspended.ToString() || s.Status == FulfillmentState.PendingFulfillmentStart.ToString())).ToList(); _context.CustomMeters.Add(customMeter); await _context._SaveChangesAsync(); // Add customMeter to db foreach (var sub in subscriptionList) { bool isEnabled = sub.Status == FulfillmentState.Subscribed.ToString() || sub.Status == FulfillmentState.Suspended.ToString(); _context.SubscriptionCustomMeterUsages.Add(new SubscriptionCustomMeterUsage(customMeter.Id, sub.SubscriptionId, isEnabled)); } await _context._SaveChangesAsync(); transaction.Commit(); } _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(CustomMeter).Name, customMeter.MeterName, offerName: offerName)); return(customMeter); }
public async Task <SubscriptionParameter> CreateAsync(SubscriptionParameter subscriptionParameter) { if (subscriptionParameter is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(SubscriptionParameter).Name), UserErrorCode.PayloadNotProvided); } // Check that the offer does not already have an armTemplateParameter with the same name if (await ExistsAsync(subscriptionParameter.SubscriptionId, subscriptionParameter.Name)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(SubscriptionParameter).Name, subscriptionParameter.Name)); } if (!await _subscriptionService.ExistsAsync(subscriptionParameter.SubscriptionId)) { throw new ArgumentException("Subscription doesn't exist."); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(SubscriptionParameter).Name, subscriptionParameter.Name, payload: JsonSerializer.Serialize(subscriptionParameter))); // Add armTemplateParameter to db _context.SubscriptionParameters.Add(subscriptionParameter); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(SubscriptionParameter).Name, subscriptionParameter.Name)); return(subscriptionParameter); }
/// <summary> /// Creates an entry in the armTemplateArmTemplateParameters table if it does not exist. /// </summary> /// <param name="armTemplateId">The ID of the armTemplate.</param> /// <param name="armTemplateParameterId">The ID of the armTemplateParameter.</param> /// <returns></returns> public async Task CreateJoinEntryAsync(long armTemplateId, long armTemplateParameterId) { if (await ExistsAsync(armTemplateId, armTemplateParameterId)) { throw new LunaServerException("This entry cannot be created since it already exists in the DB.", false); } ArmTemplateArmTemplateParameter armTemplateArmTemplateParameter = new ArmTemplateArmTemplateParameter { ArmTemplateId = armTemplateId, ArmTemplateParameterId = armTemplateParameterId }; _context.ArmTemplateArmTemplateParameters.Add(armTemplateArmTemplateParameter); await _context._SaveChangesAsync(); }
/// <summary> /// Creates a webhookParameter object within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="webhookId">The id of the webhook that the parameter is associated with.</param> /// <param name="webhookParameter">The webhookParameter to create.</param> /// <returns>The created webhookParameter.</returns> public async Task <WebhookParameter> CreateAsync(string offerName, long webhookId, WebhookParameter webhookParameter) { if (webhookParameter is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(WebhookParameter).Name), UserErrorCode.PayloadNotProvided); } if (ExpressionEvaluationUtils.ReservedParameterNames.Contains(webhookParameter.Name)) { _logger.LogInformation($"Webhook {webhookId} is referencing system parameter {webhookParameter.Name}"); return(webhookParameter); //throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(WebhookParameter).Name, // webhookParameter.Name, offerName: offerName)); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(WebhookParameter).Name, webhookParameter.Name, offerName: offerName, payload: JsonSerializer.Serialize(webhookParameter))); // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(offerName); // Check if the WebhookParameter already exists if (await ExistsAsync(offerName, webhookParameter.Name)) { // Just create a new join entry to keep track of the fact that this Webhook is using this parameter WebhookParameter webhookParameterDb = await GetAsync(offerName, webhookParameter.Name); await _webhookWebhookParameterService.CreateJoinEntryAsync(webhookId, webhookParameterDb.Id); return(webhookParameterDb); } // Set the FK to offer webhookParameter.OfferId = offer.Id; // Add webhookParameter to db _context.WebhookParameters.Add(webhookParameter); await _context._SaveChangesAsync(); await _webhookWebhookParameterService.CreateJoinEntryAsync(webhookId, webhookParameter.Id); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(WebhookParameter).Name, webhookParameter.Name, offerName: offerName)); return(webhookParameter); }
/// <summary> /// Creates an entry in the webhookWebhookParameters table if it does not exist. /// </summary> /// <param name="webhookId">The ID of the webhook.</param> /// <param name="webhookParameterId">The ID of the webhookParameter.</param> /// <returns></returns> public async Task CreateJoinEntryAsync(long webhookId, long webhookParameterId) { if (await ExistsAsync(webhookId, webhookParameterId)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(WebhookWebhookParameter).Name, $"({webhookId}, {webhookParameterId})")); } WebhookWebhookParameter webhookWebhookParameter = new WebhookWebhookParameter { WebhookId = webhookId, WebhookParameterId = webhookParameterId }; _context.WebhookWebhookParameters.Add(webhookWebhookParameter); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(WebhookWebhookParameter).Name, $"(webhookId={webhookId}, webhookParameterId={webhookParameterId})")); }
/// <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> /// Creates a customMeterDimension within a plan within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="planUniqueName">The name of the plan.</param> /// <param name="customMeterDimension">The customMeterDimension object to create.</param> /// <returns>The created customMeterDimension.</returns> public async Task <CustomMeterDimension> CreateAsync(string offerName, string planUniqueName, CustomMeterDimension customMeterDimension) { if (customMeterDimension is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(CustomMeterDimension).Name), UserErrorCode.PayloadNotProvided); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage( typeof(CustomMeterDimension).Name, customMeterDimension.Id.ToString(), offerName: offerName, planName: planUniqueName, payload: JsonSerializer.Serialize(customMeterDimension))); // Get the plan associated with the offerName and planUniqueName provided var plan = await _planService.GetAsync(offerName, planUniqueName); // Set the FK to plan customMeterDimension.PlanId = plan.Id; // Set the FK to customMeter customMeterDimension.MeterId = (await _customMeterService.GetAsync(customMeterDimension.MeterName)).Id; // Reset the PK (should not be modified in request) customMeterDimension.Id = 0; // Add customMeterDimension to db _context.CustomMeterDimensions.Add(customMeterDimension); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage( typeof(ArmTemplateParameter).Name, customMeterDimension.Id.ToString(), offerName: offerName, planName: planUniqueName)); return(customMeterDimension); }
/// <summary> /// Creates a TelemetryDataConnector. /// </summary> /// <param name="offerName">The name of the TelemetryDataConnector.</param> /// <param name="connector">The TelemetryDataConnector to create.</param> /// <returns>The created TelemetryDataConnector.</returns> public async Task <TelemetryDataConnector> CreateAsync(string name, TelemetryDataConnector connector) { if (connector is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(TelemetryDataConnector).Name), UserErrorCode.PayloadNotProvided); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(TelemetryDataConnector).Name, name, payload: JsonSerializer.Serialize(connector))); // Check that an TelemetryDataConnector with the same name does not already exist if (await ExistsAsync(name)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(TelemetryDataConnector).Name, name)); } _context.TelemetryDataConnectors.Add(connector); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(TelemetryDataConnector).Name, name)); return(connector); }
/// <summary> /// Trys to assign an IP address to the given subscriptionId. If the IP address is successfully assigned /// then it will be returned. If there are no available IP addresses to assign then an exception /// will be thrown. /// </summary> /// <param name="subscriptionId">The subscriptionId to try to assign an IpAddress to.</param> /// <param name="offerName">The name of the offer the subscription belongs to.</param> /// <param name="ipConfigName">The name of the IpConfig to get an IpAdress from.</param> /// <returns>The assigned IpAddress.</returns> public async Task <IpAddress> TryAssignIpAddress(Guid subscriptionId, string offerName, string ipConfigName) { _logger.LogInformation($"Trying to assign IP addresses to subscription ID {subscriptionId} in offer {offerName} from IP Config {ipConfigName}."); IpConfig ipConfig = await _ipConfigService.GetAsync(offerName, ipConfigName); // We only want to assign IP addresses from IP blocks that belong to the given IP config List <IpBlock> ipBlocks = await _context.IpBlocks.Where(x => x.IpConfigId == ipConfig.Id).ToListAsync(); // Keep track of IpBlock IDs that belong to the IpConfig HashSet <long> blockIds = new HashSet <long>(); foreach (IpBlock ipBlock in ipBlocks) { blockIds.Add(ipBlock.Id); } try { // Find an IpAddress that is available and belongs to one of the IpBlocks we are tracking IpAddress ipAddress = await _context.IpAddresses.Where(x => x.IsAvailable == true && blockIds.Contains(x.IpBlockId)).FirstAsync(); ipAddress.SubscriptionId = subscriptionId; ipAddress.IsAvailable = false; _context.IpAddresses.Update(ipAddress); await _context._SaveChangesAsync(); _logger.LogInformation($"The IP addresses in {ipAddress.Value} have been assigned to subscription ID {subscriptionId}."); return(ipAddress); } catch (ArgumentNullException) { throw new LunaServerException($"There are no IP addresses available in {ipConfigName}."); } }
/// <summary> /// Creates an offer. /// </summary> /// <param name="offer">The offer to create.</param> /// <returns>The created offer.</returns> public async Task <Offer> CreateAsync(Offer offer) { if (offer is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(Offer).Name), UserErrorCode.PayloadNotProvided); } // Check that an offer with the same name does not already exist if (await ExistsAsync(offer.OfferName)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(Offer).Name, offer.OfferName)); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(Offer).Name, offer.OfferName, payload: JsonSerializer.Serialize(offer))); // Generate a ContainerName for the offer offer.ContainerName = Guid.NewGuid(); // Update the offer status offer.Status = nameof(OfferStatus.Draft); // Update the offer created time offer.CreatedTime = DateTime.UtcNow; // Update the offer last updated time offer.LastUpdatedTime = offer.CreatedTime; // Add offer to db _context.Offers.Add(offer); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(Offer).Name, offer.OfferName)); return(offer); }
/// <summary> /// Transition to next state and update the subscription in database. /// </summary> /// <param name="subscription">The subscription</param> /// <param name="targetState">The target state</param> /// <param name="callerName">The caller name</param> /// <returns></returns> private async Task <Subscription> TransitToNextState(Subscription subscription, ProvisioningState targetState, [CallerMemberName] string callerName = "") { MethodInfo method = typeof(ProvisioningService).GetMethod(callerName); OutputStatesAttribute attribute = (OutputStatesAttribute)Attribute.GetCustomAttribute(method, typeof(OutputStatesAttribute)); if (!attribute.InputStates.Contains(targetState.ToString())) { throw new LunaProvisioningException( $"Cannot transit to {targetState.ToString()} state from method {callerName}.", false); } //reset retry count subscription.RetryCount = 0; subscription.ProvisioningStatus = targetState.ToString(); subscription.LastUpdatedTime = DateTime.UtcNow; _context.Subscriptions.Update(subscription); await _context._SaveChangesAsync(); return(subscription); }
/// <summary> /// Creates a customMeter. /// </summary> /// <param name="customMeter">The customMeter to create.</param> /// <returns>The created customMeter.</returns> public async Task <CustomMeter> CreateAsync(CustomMeter customMeter) { if (customMeter is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(CustomMeter).Name), UserErrorCode.PayloadNotProvided); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(CustomMeter).Name, customMeter.MeterName, payload: JsonSerializer.Serialize(customMeter))); // Check that an customMeter with the same name does not already exist if (await ExistsAsync(customMeter.MeterName)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(CustomMeter).Name, customMeter.MeterName)); } // Add customMeter to db _context.CustomMeters.Add(customMeter); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(CustomMeter).Name, customMeter.MeterName)); return(customMeter); }
/// <summary> /// Creates an offerParameter within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="offerParameter">The offerParameter to create.</param> /// <returns>The created offerParameter.</returns> public async Task <OfferParameter> CreateAsync(string offerName, OfferParameter offerParameter) { if (offerParameter is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(OfferParameter).Name), UserErrorCode.PayloadNotProvided); } // Check that the offer does not already have an offerParameter with the same parameterName if (await ExistsAsync(offerName, offerParameter.ParameterName)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(OfferParameter).Name, offerParameter.ParameterName, offerName: offerName)); } if (ExpressionEvaluationUtils.ReservedParameterNames.Contains(offerParameter.ParameterName)) { throw new LunaConflictUserException($"Parameter {offerParameter.ParameterName} is reserved. Please use a different name."); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(OfferParameter).Name, offerParameter.ParameterName, offerName: offerName, payload: JsonSerializer.Serialize(offerParameter))); // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(offerName); // Set the FK to offer offerParameter.OfferId = offer.Id; // Add offerParameter to db _context.OfferParameters.Add(offerParameter); await _context._SaveChangesAsync(); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(OfferParameter).Name, offerParameter.ParameterName, offerName: offerName)); return(offerParameter); }
/// <summary> /// Upon notification of an update of the plan from AMP, deploy the ARM template. /// </summary> /// <param name="updateModel"></param> /// <param name="operationId"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task ProcessChangePlanAsync( Subscription subscription, Guid operationId, CancellationToken cancellationToken = default) { Offer offer = await _context.Offers.FindAsync(subscription.OfferId); Plan plan = await _context.Plans.FindAsync(subscription.OfferId, subscription.PlanId); string deploymentName = $"{plan.PlanName}{offer.OfferName}{new Random().Next(0, 9999).ToString("D4")}"; // deployment name cannot exceed 64 characters, otherwise returns 400 string isvSubscriptionId = offer.HostSubscription.ToString(); // get the subscribe template for the new plan string templatePath = await GetTemplatePath( offer, plan, FulfillmentAction.Update ); object parameters = await GetTemplateParameters( offer, plan, FulfillmentAction.Update ); // deploy the ARM template. rollback to the last successful deployment if this one fails await _provisioningClient.PutDeploymentAsync( requestId : Guid.NewGuid(), correlationId : Guid.NewGuid(), subscriptionId : isvSubscriptionId, resourceGroup : subscription.ResourceGroup, deploymentName : deploymentName, templatePath : templatePath, parameters : parameters, rollbackToLastSuccessful : true, cancellationToken : cancellationToken ); // update the subscriptions table subscription.PlanId = plan.Id; subscription.Status = nameof(FulfillmentState.PendingFulfillmentStart); subscription.DeploymentName = deploymentName; subscription.OperationId = operationId; _context.Subscriptions.Update(subscription); await _context._SaveChangesAsync(); }
/// <summary> /// Enable SubscriptionCustomMeterUsage by subscription id /// </summary> /// <param name="subscriptionId">subscription id</param> /// <returns></returns> public async Task EnableSubscriptionCustomMeterUsageBySubscriptionId(Guid subscriptionId) { var subscriptionCustomMeterUsages = await _context.SubscriptionCustomMeterUsages.Where(s => s.SubscriptionId == subscriptionId).ToListAsync(); foreach (var usage in subscriptionCustomMeterUsages) { _logger.LogInformation($"Enable custom meter {usage.MeterId} for subscription {subscriptionId}."); usage.IsEnabled = true; usage.LastUpdatedTime = DateTime.UtcNow; usage.EnabledTime = usage.LastUpdatedTime; _context.SubscriptionCustomMeterUsages.Update(usage); } await _context._SaveChangesAsync(); }
/// <summary> /// Creates an ipConfig within an offer. /// </summary> /// <param name="offerName">The name of the offer.</param> /// <param name="ipConfig">The ipConfig to create.</param> /// <returns>The created ipConfig.</returns> public async Task <IpConfig> CreateAsync(string offerName, IpConfig ipConfig) { if (ipConfig is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(IpConfig).Name), UserErrorCode.PayloadNotProvided); } // Check that the offer does not already have an ipConfig with the same name if (await ExistsAsync(offerName, ipConfig.Name)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(IpConfig).Name, ipConfig.Name, offerName: offerName)); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(IpConfig).Name, ipConfig.Name, offerName: offerName, payload: JsonSerializer.Serialize(ipConfig))); // Validate that the values provided for the IpConfig are syntactically and logically correct ipConfig = validateIpConfig(ipConfig); // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(offerName); // Set the FK to offer ipConfig.OfferId = offer.Id; // Add ipConfig to db _context.IpConfigs.Add(ipConfig); await _context._SaveChangesAsync(); // Process the IpBlocks await ProcessIpBlocks(ipConfig.IpBlocks, ipConfig.Id); _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(IpConfig).Name, ipConfig.Name, offerName: offerName)); return(ipConfig); }
/// <summary> /// Creates a subscription within a plan within an offer. /// </summary> /// <param name="subscription">The subscription to create.</param> /// <returns>The created subscription.</returns> public async Task <Subscription> CreateAsync(Subscription subscription) { if (subscription is null) { throw new LunaBadRequestUserException(LoggingUtils.ComposePayloadNotProvidedErrorMessage(typeof(Subscription).Name), UserErrorCode.PayloadNotProvided); } if (await ExistsAsync(subscription.SubscriptionId)) { throw new LunaConflictUserException(LoggingUtils.ComposeAlreadyExistsErrorMessage(typeof(Subscription).Name, subscription.SubscriptionId.ToString())); } _logger.LogInformation(LoggingUtils.ComposeCreateResourceMessage(typeof(Subscription).Name, subscription.Name, offerName: subscription.OfferName, planName: subscription.PlanName, payload: JsonSerializer.Serialize(subscription))); var offerParameters = await _offerParameterService.GetAllAsync(subscription.OfferName); foreach (var param in offerParameters) { // Check if value of all offer parameters are provided with correct type if (subscription.InputParameters.Where(x => x.Name.Equals(param.ParameterName) && x.Type.Equals(param.ValueType)).Count() < 1) { throw new LunaBadRequestUserException($"Value of parameter {param.ParameterName} is not provided, or the type doesn't match.", UserErrorCode.ParameterNotProvided); } } // Get the offer associated with the offerName provided var offer = await _offerService.GetAsync(subscription.OfferName); // Get the plan associated with the planUniqueName provided var plan = await _planService.GetAsync(subscription.OfferName, subscription.PlanName); // Set the FK to offer subscription.OfferId = offer.Id; // Set the FK to plan subscription.PlanId = plan.Id; // Always set quantity to 1 to walkaround a marketplace service bug subscription.Quantity = 1; // Set the created time subscription.CreatedTime = DateTime.UtcNow; subscription.Status = nameof(FulfillmentState.PendingFulfillmentStart); subscription.ProvisioningStatus = nameof(ProvisioningState.ProvisioningPending); subscription.ProvisioningType = nameof(ProvisioningType.Subscribe); subscription.RetryCount = 0; List <CustomMeter> customMeterList = await _customMeterService.GetAllAsync(offer.OfferName); using (var transaction = await _context.BeginTransactionAsync()) { // Add subscription to db _context.Subscriptions.Add(subscription); await _context._SaveChangesAsync(); // Add subscription parameters foreach (var param in subscription.InputParameters) { param.SubscriptionId = subscription.SubscriptionId; _context.SubscriptionParameters.Add(param); } await _context._SaveChangesAsync(); foreach (var meter in customMeterList) { _context.SubscriptionCustomMeterUsages.Add(new SubscriptionCustomMeterUsage(meter.Id, subscription.SubscriptionId)); } await _context._SaveChangesAsync(); transaction.Commit(); } _logger.LogInformation(LoggingUtils.ComposeResourceCreatedMessage(typeof(Subscription).Name, subscription.Name, offerName: subscription.OfferName, planName: subscription.PlanName)); return(subscription); }
/// <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); }