コード例 #1
0
        internal async Task <bool> UpdateAsync(InstanceName instance, string requiredVersion, string sourceUrl, CancellationToken cancellationToken)
        {
            // update runtime package
            var  package = new FunctionRuntimePackage(_logger);
            bool ok      = await package.UpdateVersionAsync(requiredVersion, sourceUrl, instance, _azure, cancellationToken);

            if (!ok)
            {
                return(false);
            }

            await ForceFunctionRuntimeVersionAsync(instance, cancellationToken);

            var uploadFiles = await UpdateDefaultFilesAsync(package);

            var rules    = new AggregatorRules(_azure, _logger);
            var allRules = await rules.ListAsync(instance, cancellationToken);

            foreach (var ruleName in allRules.Select(r => r.RuleName))
            {
                _logger.WriteInfo($"Updating Rule '{ruleName}'");
                await rules.UploadRuleFilesAsync(instance, ruleName, uploadFiles, cancellationToken);
            }

            return(true);
        }
コード例 #2
0
        internal async Task <bool> UpdateAsync(InstanceName instance, string name, string filePath, string requiredVersion, string sourceUrl, CancellationToken cancellationToken)
        {
            // check runtime package
            var  package = new FunctionRuntimePackage(_logger);
            bool ok      = await package.UpdateVersionAsync(requiredVersion, sourceUrl, instance, _azure, cancellationToken);

            if (ok)
            {
                ok = await AddAsync(instance, name, filePath, cancellationToken);
            }

            return(ok);
        }
コード例 #3
0
        internal async Task <bool> AddAsync(InstanceName instance, string location, string requiredVersion, string sourceUrl, InstanceFineTuning tuning, CancellationToken cancellationToken)
        {
            string rgName = instance.ResourceGroupName;
            bool   ok     = await MakeSureResourceGroupExistsAsync(instance.IsCustom, location, rgName, cancellationToken);

            if (!ok)
            {
                return(false);
            }

            ok = await DeployArmTemplateAsync(instance, location, rgName, tuning, cancellationToken);

            if (!ok)
            {
                return(false);
            }

            // check runtime package
            var package = new FunctionRuntimePackage(logger);

            ok = await package.UpdateVersionAsync(requiredVersion, sourceUrl, instance, azure, cancellationToken);

            if (ok)
            {
                var devopsLogonData = DevOpsLogon.Load().connection;
                if (devopsLogonData.Mode == DevOpsTokenType.PAT)
                {
                    logger.WriteVerbose($"Saving Azure DevOps token");
                    ok = await ChangeAppSettingsAsync(instance, devopsLogonData, SaveMode.Default, cancellationToken);

                    if (ok)
                    {
                        logger.WriteInfo($"Azure DevOps token saved");
                    }
                    else
                    {
                        logger.WriteError($"Failed to save Azure DevOps token");
                    }
                }
                else
                {
                    logger.WriteWarning($"Azure DevOps token type {devopsLogonData.Mode} is unsupported");
                    ok = false;
                }
            }
            return(ok);
        }
コード例 #4
0
        internal async Task <bool> UpdateAsync(InstanceName instance, string requiredVersion, string sourceUrl, CancellationToken cancellationToken)
        {
            // update runtime package
            var  package = new FunctionRuntimePackage(_logger);
            bool ok      = await package.UpdateVersionAsync(requiredVersion, sourceUrl, instance, _azure, cancellationToken);

            {
                // Change V2 to V3 FUNCTIONS_EXTENSION_VERSION ~3
                var webFunctionApp = await GetWebApp(instance, cancellationToken);

                var currentAzureRuntimeVersion = webFunctionApp.GetAppSettings()
                                                 .GetValueOrDefault("FUNCTIONS_EXTENSION_VERSION");
                webFunctionApp.Update()
                .WithAppSetting("FUNCTIONS_EXTENSION_VERSION", "~3")
                .Apply();;
            }

            {
                var uploadFiles = new Dictionary <string, string>();
                using (var archive = System.IO.Compression.ZipFile.OpenRead(package.RuntimePackageFile))
                {
                    var entry = archive.Entries
                                .Single(e => string.Equals("aggregator-function.dll", e.Name, StringComparison.OrdinalIgnoreCase));

                    using (var assemblyStream = entry.Open())
                    {
                        await uploadFiles.AddFunctionDefaultFiles(assemblyStream);
                    }
                }
                //TODO handle FileNotFound Exception when trying to get resource content, and resource not found

                var rules    = new AggregatorRules(_azure, _logger);
                var allRules = await rules.ListAsync(instance, cancellationToken);

                foreach (var ruleName in allRules.Select(r => r.RuleName))
                {
                    _logger.WriteInfo($"Updating Rule '{ruleName}'");
                    await rules.UploadRuleFilesAsync(instance, ruleName, uploadFiles, cancellationToken);
                }
            }

            return(false);
        }
コード例 #5
0
        internal async Task <bool> AddAsync(InstanceName instance, string location, string requiredVersion, string sourceUrl, CancellationToken cancellationToken)
        {
            string rgName = instance.ResourceGroupName;

            logger.WriteVerbose($"Checking if Resource Group {rgName} already exists");
            if (!await azure.ResourceGroups.ContainAsync(rgName, cancellationToken))
            {
                if (instance.IsCustom)
                {
                    logger.WriteError($"Resource group {rgName} is custom and cannot be created.");
                    return(false);
                }

                logger.WriteVerbose($"Creating resource group {rgName}");
                await azure.ResourceGroups
                .Define(rgName)
                .WithRegion(location)
                .CreateAsync();

                logger.WriteInfo($"Resource group {rgName} created.");
            }

            // IDEA the template should create a Storage account and/or a Key Vault for Rules' use
            // TODO https://github.com/gjlumsden/AzureFunctionsSlots suggest that slots must be created in template
            var    resourceName = "aggregator.cli.Instances.instance-template.json";
            string armTemplateString;
            var    assembly = Assembly.GetExecutingAssembly();

            using (Stream stream = assembly.GetManifestResourceStream(resourceName))
                using (StreamReader reader = new StreamReader(stream))
                {
                    armTemplateString = await reader.ReadToEndAsync();
                }

            var parsedTemplate = JObject.Parse(armTemplateString);

            // sanity checks
            if (parsedTemplate.SelectToken("parameters.appName") == null)
            {
                // not good, blah
                logger.WriteWarning($"Something is wrong with the ARM template");
            }

            string appName        = instance.FunctionAppName;
            var    infoVersion    = GetCustomAttribute <AssemblyInformationalVersionAttribute>();
            var    templateParams = new Dictionary <string, Dictionary <string, object> > {
                // TODO give use more control by setting more parameters
                { "location", new Dictionary <string, object> {
                      { "value", location }
                  } },
                { "storageAccountType", new Dictionary <string, object> {
                      { "value", "Standard_LRS" }
                  } },
                { "appName", new Dictionary <string, object> {
                      { "value", appName }
                  } },
                { "aggregatorVersion", new Dictionary <string, object> {
                      { "value", infoVersion.InformationalVersion }
                  } },
                { "hostingPlanSkuName", new Dictionary <string, object> {
                      { "value", "Y1" }
                  } },
                { "hostingPlanSkuTier", new Dictionary <string, object> {
                      { "value", "Dynamic" }
                  } },
            };

            string deploymentName = SdkContext.RandomResourceName("aggregator", 24);

            logger.WriteInfo($"Started deployment (id: {deploymentName})");
            var deployment = await azure.Deployments.Define(deploymentName)
                             .WithExistingResourceGroup(rgName)
                             .WithTemplate(armTemplateString)
                             .WithParameters(templateParams)
                             .WithMode(DeploymentMode.Incremental)
                             .CreateAsync(cancellationToken);

            // poll
            const int pollIntervalInSeconds = 3;
            int       totalDelay            = 0;

            while (!(StringComparer.OrdinalIgnoreCase.Equals(deployment.ProvisioningState, "Succeeded") ||
                     StringComparer.OrdinalIgnoreCase.Equals(deployment.ProvisioningState, "Failed") ||
                     StringComparer.OrdinalIgnoreCase.Equals(deployment.ProvisioningState, "Cancelled")))
            {
                SdkContext.DelayProvider.Delay(pollIntervalInSeconds * 1000);
                totalDelay += pollIntervalInSeconds;
                logger.WriteVerbose($"Deployment running ({totalDelay}s)");
                await deployment.RefreshAsync(cancellationToken);
            }
            logger.WriteInfo($"Deployment {deployment.ProvisioningState}");

            // check runtime package
            var  package = new FunctionRuntimePackage(logger);
            bool ok      = await package.UpdateVersionAsync(requiredVersion, sourceUrl, instance, azure, cancellationToken);

            if (ok)
            {
                var devopsLogonData = DevOpsLogon.Load().connection;
                if (devopsLogonData.Mode == DevOpsTokenType.PAT)
                {
                    logger.WriteVerbose($"Saving Azure DevOps token");
                    ok = await ChangeAppSettingsAsync(instance, devopsLogonData, SaveMode.Default, cancellationToken);

                    if (ok)
                    {
                        logger.WriteInfo($"Azure DevOps token saved");
                    }
                    else
                    {
                        logger.WriteError($"Failed to save Azure DevOps token");
                    }
                }
                else
                {
                    logger.WriteWarning($"Azure DevOps token type {devopsLogonData.Mode} is unsupported");
                    ok = false;
                }
            }
            return(ok);
        }