예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        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();
        }
예제 #8
0
        /// <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})"));
        }
예제 #10
0
        /// <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);
        }
예제 #13
0
        /// <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}.");
            }
        }
예제 #14
0
        /// <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);
        }
예제 #15
0
        /// <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);
        }
예제 #17
0
        /// <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);
        }
예제 #18
0
        /// <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();
        }
예제 #19
0
        /// <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();
        }
예제 #20
0
        /// <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);
        }
예제 #21
0
        /// <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);
        }
예제 #22
0
        /// <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);
        }