Beispiel #1
0
        /// <summary>
        /// Initializes the dependency manger and performs the following:
        /// - Parse functionAppRoot\requirements.psd1 file and create a list of dependencies to install.
        /// - Set the DependenciesPath which gets used in 'SetupWellKnownPaths'.
        /// - Determines if the dependency module needs to be installed by checking the latest available version
        ///   in the PSGallery and the destination path (to see if it is already installed).
        /// - Set the destination path (if running in Azure vs local) where the function app dependencies will be installed.
        /// </summary>
        internal void Initialize(FunctionLoadRequest request)
        {
            if (!request.ManagedDependencyEnabled)
            {
                return;
            }

            try
            {
                // Resolve the FunctionApp root path.
                var functionAppRootPath = Path.GetFullPath(Path.Join(request.Metadata.Directory, ".."));

                // Resolve the managed dependencies installation path.
                DependenciesPath = GetManagedDependenciesPath(functionAppRootPath);

                // Parse and process the function app dependencies defined in requirements.psd1.
                Hashtable entries = ParsePowerShellDataFile(functionAppRootPath, RequirementsPsd1FileName);
                foreach (DictionaryEntry entry in entries)
                {
                    // A valid entry is of the form: 'ModuleName'='MajorVersion.*"
                    string name    = (string)entry.Key;
                    string version = (string)entry.Value;

                    // Validates that the module name is a supported dependency.
                    ValidateModuleName(name);

                    // Validate the module version.
                    string majorVersion  = GetMajorVersion(version);
                    string latestVersion = DependencyManagementUtils.GetModuleLatestSupportedVersion(name, majorVersion);
                    ValidateModuleMajorVersion(name, majorVersion, latestVersion);

                    // Before installing the module, check the path to see if it is already installed.
                    var moduleVersionFolderPath = Path.Combine(DependenciesPath, name, latestVersion);
                    if (!Directory.Exists(moduleVersionFolderPath))
                    {
                        _shouldUpdateFunctionAppDependencies = true;
                    }

                    // Create a DependencyInfo object and add it to the list of dependencies to install.
                    var dependencyInfo = new DependencyInfo(name, majorVersion, latestVersion);
                    Dependencies.Add(dependencyInfo);
                }
            }
            catch (Exception e)
            {
                // Reset DependenciesPath and Dependencies.
                DependenciesPath = null;
                Dependencies.Clear();

                var errorMsg = string.Format(PowerShellWorkerStrings.FailToInstallFuncAppDependencies, e.Message);
                throw new DependencyInstallationException(errorMsg, e);
            }
        }
        private List <DependencyInfo> GetExactVersionsOfDependencies(
            IEnumerable <DependencyManifestEntry> dependencies)
        {
            var result = new List <DependencyInfo>();

            foreach (var entry in dependencies)
            {
                var dependencyInfo = new DependencyInfo(entry.Name, GetExactVersion(entry));
                result.Add(dependencyInfo);
            }

            return(result);
        }
        private void InstallModule(DependencyInfo module, string installingPath, PowerShell pwsh, ILogger logger)
        {
            logger.Log(isUserOnlyLog: false, LogLevel.Trace, string.Format(PowerShellWorkerStrings.StartedInstallingModule, module.Name, module.ExactVersion));

            int tries = 1;

            while (true)
            {
                try
                {
                    _moduleProvider.SaveModule(pwsh, module.Name, module.ExactVersion, installingPath);

                    var message = string.Format(PowerShellWorkerStrings.ModuleHasBeenInstalled, module.Name, module.ExactVersion);
                    logger.Log(isUserOnlyLog: false, LogLevel.Trace, message);

                    break;
                }
                catch (Exception e)
                {
                    string currentAttempt = GetCurrentAttemptMessage(tries);
                    var    errorMsg       = string.Format(PowerShellWorkerStrings.FailToInstallModule, module.Name, module.ExactVersion, currentAttempt, e.Message);
                    logger.Log(isUserOnlyLog: false, LogLevel.Error, errorMsg);

                    if (tries >= MaxNumberOfTries)
                    {
                        errorMsg = string.Format(PowerShellWorkerStrings.FailToInstallFuncAppDependencies, e.Message);
                        throw new DependencyInstallationException(errorMsg, e);
                    }
                }

                // Wait for 2^(tries-1) seconds between retries. In this case, it would be 1, 2, and 4 seconds, respectively.
                var waitTimeSpan = TimeSpan.FromSeconds(Math.Pow(2, tries - 1));
                Thread.Sleep(waitTimeSpan);

                tries++;
            }
        }
        /// <summary>
        /// Initializes the dependency manger and performs the following:
        /// - Parse functionAppRoot\requirements.psd1 file and create a list of dependencies to install.
        /// - Set the DependenciesPath which gets used in 'SetupWellKnownPaths'.
        /// - Determines if the dependency module needs to be installed by checking the latest available version
        ///   in the PSGallery and the destination path (to see if it is already installed).
        /// - Set the destination path (if running in Azure vs local) where the function app dependencies will be installed.
        /// </summary>
        internal void Initialize(FunctionLoadRequest request)
        {
            if (!request.ManagedDependencyEnabled)
            {
                return;
            }

            try
            {
                // Resolve the FunctionApp root path.
                var functionAppRootPath = Path.GetFullPath(Path.Join(request.Metadata.Directory, ".."));

                // Resolve the managed dependencies installation path.
                DependenciesPath = GetManagedDependenciesPath(functionAppRootPath);

                // Parse and process the function app dependencies defined in requirements.psd1.
                Hashtable entries = ParsePowerShellDataFile(functionAppRootPath, RequirementsPsd1FileName);
                foreach (DictionaryEntry entry in entries)
                {
                    // A valid entry is of the form: 'ModuleName'='MajorVersion.*"
                    string name    = (string)entry.Key;
                    string version = (string)entry.Value;

                    // Validates that the module name is a supported dependency.
                    ValidateModuleName(name);

                    // Validate the module version.
                    string majorVersion = GetMajorVersion(version);

                    // Try to connect to the PSGallery to get the latest module supported version.
                    string latestVersion = null;
                    try
                    {
                        latestVersion = GetModuleLatestSupportedVersion(name, majorVersion);
                    }
                    catch (Exception e)
                    {
                        // If we fail to get the latest module version (this could be because the PSGallery is down).

                        // Check to see if there are previous managed dependencies installed. If this is the case,
                        // DependenciesPath is already set, so Get-Module will be able to find the modules.
                        var pathToInstalledModule = Path.Combine(DependenciesPath, name);
                        if (Directory.Exists(pathToInstalledModule))
                        {
                            // Message to the user for skipped dependencies upgrade.
                            _dependenciesNotUpdatedMessage = string.Format(PowerShellWorkerStrings.DependenciesUpgradeSkippedMessage, e.Message);

                            // Make sure that function app dependencies will NOT be installed, just continue with the function app execution.
                            _shouldUpdateFunctionAppDependencies = false;
                            return;
                        }

                        // Otherwise, rethrow and stop the function app execution.
                        throw;
                    }

                    // Before installing the module, check the path to see if it is already installed.
                    var moduleVersionFolderPath = Path.Combine(DependenciesPath, name, latestVersion);
                    if (!Directory.Exists(moduleVersionFolderPath))
                    {
                        _shouldUpdateFunctionAppDependencies = true;
                    }

                    // Create a DependencyInfo object and add it to the list of dependencies to install.
                    var dependencyInfo = new DependencyInfo(name, majorVersion, latestVersion);
                    Dependencies.Add(dependencyInfo);
                }
            }
            catch (Exception e)
            {
                // Reset DependenciesPath and Dependencies.
                DependenciesPath = null;
                Dependencies.Clear();

                var errorMsg = string.Format(PowerShellWorkerStrings.FailToInstallFuncAppDependencies, e.Message);
                throw new DependencyInstallationException(errorMsg, e);
            }
        }