public async Task Validate()

in src/AWS.Deploy.Common/Recipes/Validation/RecipeValidators/BeanstalkInstanceTypeValidator.cs [39:131]


    public async Task<ValidationResult> Validate(Recommendation recommendation, IDeployToolValidationContext deployValidationContext)
    {
        string? instanceType;
        try
        {
            instanceType = _optionSettingHandler.GetOptionSettingValue<string>(recommendation, _optionSettingHandler.GetOptionSetting(recommendation, InstanceTypeOptionSettingsId));
        }
        catch (OptionSettingItemDoesNotExistException)
        {
            return await ValidationResult.FailedAsync("Could not find a valid value for Instance Type " +
                "as part of of the Elastic Beanstalk deployment configuration. Please provide a valid value and try again.");
        }

        // If the instance type is null and this is a new deployment, CDK & Beanstalk will automatically set the appropriate instance type
        // based on the defined environment architecture. However, on a redeployment, if the user changes the environment architecture
        // but does not explicitly update the instance type, then CDK & Beanstalk do not automatically update the instance type
        // which would cause a failed deployment. In this case, we need to let the user know that the instance type needs to be updated.
        if (string.IsNullOrEmpty(instanceType))
        {
            // If this is a new deployment, CDK & Beanstalk will set up the proper instance type and we do not need to perform validation
            if (!recommendation.IsExistingCloudApplication)
                return await ValidationResult.ValidAsync();

            string? applicationName;
            string? environmentName;

            try
            {
                applicationName = _optionSettingHandler.GetOptionSettingValue<string>(recommendation, _optionSettingHandler.GetOptionSetting(recommendation, ApplicationNameOptionSettingsId));
                if (string.IsNullOrEmpty(applicationName))
                    return await ValidationResult.FailedAsync("Could not find a valid value for Application Name " +
                    "as part of of the Elastic Beanstalk deployment configuration. Please provide a valid value and try again.");
                environmentName = _optionSettingHandler.GetOptionSettingValue<string>(recommendation, _optionSettingHandler.GetOptionSetting(recommendation, EnvironmentNameOptionSettingsId));
                if (string.IsNullOrEmpty(environmentName))
                    return await ValidationResult.FailedAsync("Could not find a valid value for Environment Name " +
                    "as part of of the Elastic Beanstalk deployment configuration. Please provide a valid value and try again.");
            }
            catch (OptionSettingItemDoesNotExistException)
            {
                return await ValidationResult.FailedAsync("Could not find a valid value for Environment Name " +
                    "as part of of the Elastic Beanstalk deployment configuration. Please provide a valid value and try again.");
            }

            // In order to retrieve the Instance Type from Elastic Beanstalk, we need to list the Option Settings of the configuration settings and look for the option
            // with the namespace 'aws:autoscaling:launchconfiguration' and name 'InstanceType'.
            var environmentSettings = await _awsResourceQueryer.DescribeElasticBeanstalkConfigurationSettings(applicationName, environmentName);
            var environmentInstanceTypes = new HashSet<string>();
            foreach (var environmentSetting in environmentSettings)
            {
                foreach (var optionSetting in environmentSetting.OptionSettings)
                {
                    if (optionSetting.Namespace.Equals("aws:autoscaling:launchconfiguration") &&
                        optionSetting.OptionName.Equals("InstanceType"))
                    {
                        environmentInstanceTypes.Add(optionSetting.Value);
                    }
                }
            }

            // Once we have the instance types, we need to retrieve the supported architecture for those instance types.
            var environmentArchitectures = new HashSet<string>();
            foreach (var environmentInstanceType in environmentInstanceTypes)
            {
                var describeInstanceTypeResponse = await _awsResourceQueryer.DescribeInstanceType(environmentInstanceType);
                describeInstanceTypeResponse?.ProcessorInfo.SupportedArchitectures.ForEach((x) => environmentArchitectures.Add(x));
            }

            // We check if the selected instance types support the architecture we are trying to deploy to.
            if (!environmentArchitectures.Contains(recommendation.DeploymentBundle.EnvironmentArchitecture.ToString(), StringComparer.InvariantCultureIgnoreCase))
            {
                return await ValidationResult.FailedAsync(
                    $"The Elastic Beanstalk application is currently using the Instance Types '{string.Join(",", environmentInstanceTypes)}' " +
                    $"which do not support the currently selected Environment Architecture '{recommendation.DeploymentBundle.EnvironmentArchitecture}'. " +
                    "Please select an Instance Type that supports the currently selected Environment Architecture.");
            }
        }
        else
        {
            // We need to retrieve the supported architecture for the selected instance type.
            var describeInstanceTypeResponse = await _awsResourceQueryer.DescribeInstanceType(instanceType);
            var environmentArchitectures = describeInstanceTypeResponse?.ProcessorInfo.SupportedArchitectures ?? new List<string>();
            // We check if the selected instance types support the architecture we are trying to deploy to.
            if (!environmentArchitectures.Contains(recommendation.DeploymentBundle.EnvironmentArchitecture.ToString(), StringComparer.InvariantCultureIgnoreCase))
            {
                return await ValidationResult.FailedAsync(
                    $"The Elastic Beanstalk application is currently using the Instance Type '{string.Join(",", instanceType)}' " +
                    $"which do not support the currently selected Environment Architecture '{recommendation.DeploymentBundle.EnvironmentArchitecture}'. " +
                    "Please select an Instance Type that supports the currently selected Environment Architecture.");
            }
        }

        return await ValidationResult.ValidAsync();
    }