Example #1
0
        /// <summary>
        /// Installs function app dependencies specified in functionAppRoot\requirements.psd1.
        /// </summary>
        internal void InstallFunctionAppDependencies(PowerShell pwsh, ILogger logger)
        {
            try
            {
                // Install the function dependencies.
                logger.Log(LogLevel.Trace, PowerShellWorkerStrings.InstallingFunctionAppDependentModules, isUserLog: true);

                if (Directory.Exists(DependenciesPath))
                {
                    // Save-Module supports downloading side-by-size module versions. However, we only want to keep one version at the time.
                    // If the ManagedDependencies folder exits, remove all its contents.
                    DependencyManagementUtils.EmptyDirectory(DependenciesPath);
                }
                else
                {
                    // If the destination path does not exist, create it.
                    Directory.CreateDirectory(DependenciesPath);
                }

                try
                {
                    foreach (DependencyInfo module in Dependencies)
                    {
                        string moduleName    = module.Name;
                        string latestVersion = module.LatestVersion;

                        // Save the module to the given path
                        pwsh.AddCommand("PowerShellGet\\Save-Module")
                        .AddParameter("Repository", Repository)
                        .AddParameter("Name", moduleName)
                        .AddParameter("RequiredVersion", latestVersion)
                        .AddParameter("Path", DependenciesPath)
                        .AddParameter("Force", true)
                        .AddParameter("ErrorAction", "Stop")
                        .InvokeAndClearCommands();

                        var message = string.Format(PowerShellWorkerStrings.ModuleHasBeenInstalled, moduleName, latestVersion);
                        logger.Log(LogLevel.Trace, message, isUserLog: true);
                    }
                }
                finally
                {
                    // Clean up
                    pwsh.AddCommand(Utils.RemoveModuleCmdletInfo)
                    .AddParameter("Name", "PackageManagement, PowerShellGet")
                    .AddParameter("Force", true)
                    .AddParameter("ErrorAction", "SilentlyContinue")
                    .InvokeAndClearCommands();
                }
            }
            catch (Exception e)
            {
                var errorMsg = string.Format(PowerShellWorkerStrings.FailToInstallFuncAppDependencies, e.Message);
                _dependencyError = new DependencyInstallationException(errorMsg, e);
            }
        }
Example #2
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);
            }
        }
 /// <summary>
 /// Sets/prepares the destination path where the function app dependencies will be installed.
 /// </summary>
 internal void SetDependenciesDestinationPath(string path)
 {
     // Save-Module supports downloading side-by-size module versions. However, we only want to keep one version at the time.
     // If the ManagedDependencies folder exits, remove all its contents.
     if (Directory.Exists(path))
     {
         DependencyManagementUtils.EmptyDirectory(path);
     }
     else
     {
         // If the destination path does not exist, create it.
         // If the user does not have write access to the path, an exception will be raised.
         try
         {
             Directory.CreateDirectory(path);
         }
         catch (Exception e)
         {
             var errorMsg = string.Format(PowerShellWorkerStrings.FailToCreateFunctionAppDependenciesDestinationPath, path, e.Message);
             throw new InvalidOperationException(errorMsg);
         }
     }
 }