Beispiel #1
0
        /// <summary>
        /// <para>1. list all package</para>
        /// <para>2. for each package: if operation is 'install' and provisionState is 'success' and no installation lock</para>
        /// <para>      Update operation to null</para>
        /// </summary>
        private bool UpdateArmSettingsForSuccessInstallation()
        {
            var batchUpdateLock = SiteExtensionBatchUpdateStatusLock.CreateLock(_environment.SiteExtensionSettingsPath);

            bool isAnyUpdate = false;

            bool islocked = batchUpdateLock.TryLockOperation(() =>
            {
                var tracer           = _traceFactory.GetTracer();
                string[] packageDirs = FileSystemHelpers.GetDirectories(_environment.SiteExtensionSettingsPath);
                foreach (var dir in packageDirs)
                {
                    var dirInfo = new DirectoryInfo(dir);   // arm setting folder name is same as package id
                    SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, dirInfo.Name, tracer);
                    if (string.Equals(armSettings.Operation, Constants.SiteExtensionOperationInstall, StringComparison.OrdinalIgnoreCase) &&
                        string.Equals(armSettings.ProvisioningState, Constants.SiteExtensionProvisioningStateSucceeded, StringComparison.OrdinalIgnoreCase))
                    {
                        try
                        {
                            armSettings.Operation = null;
                            isAnyUpdate           = true;
                        }
                        catch (Exception ex)
                        {
                            tracer.TraceError(ex);
                            // no-op
                        }
                    }
                }
            }, TimeSpan.FromSeconds(5));

            return(islocked && isAnyUpdate);
        }
Beispiel #2
0
        /// <summary>
        /// <para>Scan every site extensions, check if there is any successful installation</para>
        /// <para>Looking for below cases:</para>
        /// <para>if not install to webroot, trigger restart; if install to webroot and with applicationHost.xdt file, trigger restart.</para>
        /// </summary>
        /// <param name="siteExtensionStatusRoot">should be $ROOT\site\siteextensions</param>
        /// <param name="siteExtensionRoot">should be $ROOT\SiteExtensions</param>
        public static bool IsAnyInstallationRequireRestart(string siteExtensionStatusRoot, string siteExtensionRoot, ITracer tracer, IAnalytics analytics)
        {
            try
            {
                using (tracer.Step("Checking if there is any installation require site restart ..."))
                {
                    string[] packageDirs = FileSystemHelpers.GetDirectories(siteExtensionStatusRoot);
                    // folder name is the package id
                    foreach (var dir in packageDirs)
                    {
                        try
                        {
                            DirectoryInfo dirInfo        = new DirectoryInfo(dir);
                            var           statusSettings = new SiteExtensionStatus(siteExtensionStatusRoot, dirInfo.Name, tracer);
                            if (statusSettings.IsSiteExtensionRequireRestart(siteExtensionRoot))
                            {
                                return(true);
                            }
                        }
                        catch (Exception ex)
                        {
                            analytics.UnexpectedException(ex, trace: false);
                            tracer.TraceError(ex, "Failed to query {0} under {1}, continus to check others ...", _statusSettingsFileName, dir);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                analytics.UnexpectedException(ex, trace: false);
                tracer.TraceError(ex, "Not able to query directory under {0}", siteExtensionStatusRoot);
            }

            return(false);
        }
        private async Task <TriggersPayload> GetTriggersLocalFiles()
        {
            var functionsPath = Environment.CurrentDirectory;

            if (GlobalCoreToolsSettings.CurrentWorkerRuntime == WorkerRuntime.dotnet)
            {
                if (DotnetHelpers.CanDotnetBuild())
                {
                    var outputPath = Path.Combine("bin", "output");
                    await DotnetHelpers.BuildDotnetProject(outputPath, string.Empty, showOutput : false);

                    functionsPath = Path.Combine(Environment.CurrentDirectory, outputPath);
                }
            }

            var functionJsonFiles = FileSystemHelpers
                                    .GetDirectories(functionsPath)
                                    .Select(d => Path.Combine(d, "function.json"))
                                    .Where(FileSystemHelpers.FileExists)
                                    .Select(f => (filePath: f, content: FileSystemHelpers.ReadAllTextFromFile(f)));

            var functionsJsons = functionJsonFiles
                                 .Select(t => (filePath: t.filePath, jObject: JsonConvert.DeserializeObject <JObject>(t.content)))
                                 .Where(b => b.jObject["bindings"] != null)
                                 .ToDictionary(k => Path.GetFileName(Path.GetDirectoryName(k.filePath)), v => v.jObject);

            var hostJson = JsonConvert.DeserializeObject <JObject>(FileSystemHelpers.ReadAllTextFromFile("host.json"));

            return(new TriggersPayload
            {
                HostJson = hostJson,
                FunctionsJson = functionsJsons
            });
        }
Beispiel #4
0
 private static string GetLatestPreInstalledExtensionVersion(string id)
 {
     try
     {
         IEnumerable <string> pathStrings = FileSystemHelpers.GetDirectories("D:\\Program Files (x86)\\SiteExtensions\\" + id);
         SemanticVersion      maxVersion  = pathStrings.Max(path =>
         {
             string versionString = FileSystemHelpers.DirectoryInfoFromDirectoryName(path).Name;
             SemanticVersion semVer;
             if (SemanticVersion.TryParse(versionString, out semVer))
             {
                 return(semVer);
             }
             else
             {
                 return(new SemanticVersion(0, 0, 0, 0));
             }
         });
         return(maxVersion.ToString());
     }
     catch (IOException)
     {
         return(null);
     }
 }
Beispiel #5
0
        private static string GetPreInstalledLatestVersion(string directory)
        {
            if (!FileSystemHelpers.DirectoryExists(directory))
            {
                return(null);
            }

            string[] pathStrings = FileSystemHelpers.GetDirectories(directory);

            if (pathStrings.Length == 0)
            {
                return(null);
            }

            return(pathStrings.Max(path =>
            {
                string versionString = FileSystemHelpers.DirectoryInfoFromDirectoryName(path).Name;
                SemanticVersion semVer;
                if (SemanticVersion.TryParse(versionString, out semVer))
                {
                    return semVer;
                }
                else
                {
                    return new SemanticVersion(0, 0, 0, 0);
                }
            }).ToString());
        }
Beispiel #6
0
        private void DeleteFilesAndDirsExcept(string fileToKeep, string dirToKeep, ITracer tracer)
        {
            // Best effort. Using the "Safe" variants does retries and swallows exceptions but
            // we may catch something non-obvious.
            try
            {
                var files = FileSystemHelpers.GetFiles(_environment.ZipTempPath, "*")
                            .Where(p => !PathUtilityFactory.Instance.PathsEquals(p, fileToKeep));

                foreach (var file in files)
                {
                    FileSystemHelpers.DeleteFileSafe(file);
                }

                var dirs = FileSystemHelpers.GetDirectories(_environment.ZipTempPath)
                           .Where(p => !PathUtilityFactory.Instance.PathsEquals(p, dirToKeep));

                foreach (var dir in dirs)
                {
                    FileSystemHelpers.DeleteDirectorySafe(dir);
                }
            }
            catch (Exception ex)
            {
                tracer.TraceError(ex, "Exception encountered during zip folder cleanup");
                throw;
            }
        }
Beispiel #7
0
        public async Task <IEnumerable <FunctionEnvelope> > ListFunctionsConfigAsync(FunctionTestData packageLimit = null) // null means no limit
        {
            var configList = await Task.WhenAll(
                FileSystemHelpers
                .GetDirectories(_environment.FunctionsPath)
                .Select(d => TryGetFunctionConfigAsync(Path.GetFileName(d), packageLimit)));

            // TryGetFunctionConfigAsync checks the existence of function.json
            return(configList.Where(c => c != null));
        }
Beispiel #8
0
 public IEnumerable <string> EnumerateFunctionFiles()
 {
     foreach (var functionPath in FileSystemHelpers.GetDirectories(_environment.WebRootPath))
     {
         var functionJson = Path.Combine(functionPath, FunctionJsonFile);
         if (FileSystemHelpers.FileExists(functionJson))
         {
             yield return(functionJson);
         }
     }
 }
Beispiel #9
0
        public async Task <IEnumerable <FunctionEnvelope> > ListFunctionsConfigAsync()
        {
            var configList = await Task.WhenAll(
                FileSystemHelpers
                .GetDirectories(_environment.FunctionsPath)
                .Select(d => Path.Combine(d, Constants.FunctionsConfigFile))
                .Where(FileSystemHelpers.FileExists)
                .Select(f => TryGetFunctionConfigAsync(Path.GetFileName(Path.GetDirectoryName(f)))));

            return(configList.Where(c => c != null));
        }
Beispiel #10
0
        private Boolean IsFolderModified(JObject fileObj, string directoryPath)
        {
            //Fetch all files in this directory
            string[] filePaths = FileSystemHelpers.GetFiles(directoryPath, "*");

            if (filePaths != null)
            {
                foreach (string filePath in filePaths)
                {
                    Console.WriteLine(filePath);
                    //If manifest does not contain an entry for this file
                    //It means the file was newly added
                    //We need to scan as this is a modification
                    JToken val = null;
                    if (!fileObj.TryGetValue(filePath, out val))
                    {
                        return(true);
                    }
                    //Modified time in manifest
                    String lastModTime = (string)fileObj[filePath];
                    //Current modified time
                    String currModTime = FileSystemHelpers.GetDirectoryLastWriteTimeUtc(filePath).ToString();

                    //If they are different
                    //It means file has been modified after last scan
                    if (!currModTime.Equals(lastModTime))
                    {
                        return(true);
                    }
                }
            }


            //Fetch all the child directories of this directory
            string[] direcPaths = FileSystemHelpers.GetDirectories(directoryPath);

            if (direcPaths != null)
            {
                //Do recursive comparison of all files in the child directories
                foreach (string direcPath in direcPaths)
                {
                    if (IsFolderModified(fileObj, direcPath))
                    {
                        return(true);
                    }
                }
            }

            //No modifications found
            return(false);
        }
Beispiel #11
0
        private static IEnumerable <ScanOverviewResult> EnumerateResults(String mainScanDir)
        {
            if (FileSystemHelpers.DirectoryExists(mainScanDir))
            {
                foreach (String scanFolderPath in FileSystemHelpers.GetDirectories(mainScanDir))
                {
                    ScanOverviewResult result     = new ScanOverviewResult();
                    ScanStatusResult   scanStatus = ReadScanStatusFile("", "", Constants.ScanStatusFile, scanFolderPath);
                    result.Status = scanStatus;

                    yield return(result);
                }
            }
        }
Beispiel #12
0
        public static bool IsAnyPendingLock(string rootPath, ITracer tracer)
        {
            bool hasPendingLock = false;

            try
            {
                using (tracer.Step("Checking if there is other pending installation ..."))
                {
                    string[] packageDirs = FileSystemHelpers.GetDirectories(rootPath);
                    foreach (var dir in packageDirs)
                    {
                        string[] lockFiles = FileSystemHelpers.GetFiles(dir, string.Format("*{0}", LockNameSuffix));
                        foreach (var file in lockFiles)
                        {
                            // If there's no file then there's no process holding onto it
                            if (!FileSystemHelpers.FileExists(file))
                            {
                                continue;
                            }

                            try
                            {
                                // If there is a file, lets see if someone has an open handle to it, or if it's
                                // just hanging there for no reason
                                using (FileSystemHelpers.OpenFile(file, FileMode.Open, FileAccess.Write, FileShare.Read)) { }
                            }
                            catch
                            {
                                hasPendingLock = true;
                                break;
                            }
                        }

                        if (hasPendingLock)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // no-op
                tracer.TraceError(ex, "Failed to check pending installation lock. Assume there is no pending lock.");
            }

            return(hasPendingLock);
        }
        /// <summary>
        /// <para>1. list all package</para>
        /// <para>2. for each package: if operation is 'install' and provisionState is 'success' and no installation lock</para>
        /// <para>      Update operation to null</para>
        /// </summary>
        private bool UpdateArmSettingsForSuccessInstallation()
        {
            var tracer = _traceFactory.GetTracer();

            using (tracer.Step("Checking if there is any installation finished recently, if there is one, update its status."))
            {
                var batchUpdateLock = SiteExtensionBatchUpdateStatusLock.CreateLock(_environment.SiteExtensionSettingsPath);

                bool isAnyUpdate = false;

                try
                {
                    batchUpdateLock.LockOperation(() =>
                    {
                        string[] packageDirs = FileSystemHelpers.GetDirectories(_environment.SiteExtensionSettingsPath);
                        foreach (var dir in packageDirs)
                        {
                            var dirInfo = new DirectoryInfo(dir);   // arm setting folder name is same as package id
                            SiteExtensionStatus armSettings = new SiteExtensionStatus(_environment.SiteExtensionSettingsPath, dirInfo.Name, tracer);
                            if (string.Equals(armSettings.Operation, Constants.SiteExtensionOperationInstall, StringComparison.OrdinalIgnoreCase) &&
                                string.Equals(armSettings.ProvisioningState, Constants.SiteExtensionProvisioningStateSucceeded, StringComparison.OrdinalIgnoreCase))
                            {
                                try
                                {
                                    armSettings.Operation = null;
                                    isAnyUpdate           = true;
                                    tracer.Trace("Updated {0}", dir);
                                }
                                catch (Exception ex)
                                {
                                    tracer.TraceError(ex);
                                    // no-op
                                }
                            }
                        }
                    }, "Updating SiteExtension success status", TimeSpan.FromSeconds(5));

                    return(isAnyUpdate);
                }
                catch (LockOperationException)
                {
                    return(false);
                }
            }
        }
        public static bool IsAnyPendingLock(string rootPath)
        {
            bool hasPendingLock = false;

            try
            {
                string[] packageDirs = FileSystemHelpers.GetDirectories(rootPath);
                foreach (var dir in packageDirs)
                {
                    string[] lockFiles = FileSystemHelpers.GetFiles(dir, string.Format("*{0}", LockNameSuffix));
                    foreach (var file in lockFiles)
                    {
                        // If there's no file then there's no process holding onto it
                        if (!FileSystemHelpers.FileExists(file))
                        {
                            continue;
                        }

                        try
                        {
                            // If there is a file, lets see if someone has an open handle to it, or if it's
                            // just hanging there for no reason
                            using (FileSystemHelpers.OpenFile(file, FileMode.Open, FileAccess.Write, FileShare.Read)) { }
                        }
                        catch
                        {
                            hasPendingLock = true;
                            break;
                        }
                    }

                    if (hasPendingLock)
                    {
                        break;
                    }
                }
            }
            catch
            {
                // no-op
            }

            return(hasPendingLock);
        }
Beispiel #15
0
        private IEnumerable <DeployResult> EnumerateResults()
        {
            if (!FileSystemHelpers.DirectoryExists(_environment.DeploymentsPath))
            {
                yield break;
            }

            string activeDeploymentId = _status.ActiveDeploymentId;
            bool   isDeploying        = IsDeploying;

            foreach (var id in FileSystemHelpers.GetDirectories(_environment.DeploymentsPath))
            {
                DeployResult result = GetResult(id, activeDeploymentId, isDeploying);

                if (result != null)
                {
                    yield return(result);
                }
            }
        }
Beispiel #16
0
        private static string GetPreInstalledLatestVersion(string directory)
        {
            IEnumerable <string> pathStrings = FileSystemHelpers.GetDirectories(directory);

            SemanticVersion maxVersion = pathStrings.Max(path =>
            {
                string versionString = FileSystemHelpers.DirectoryInfoFromDirectoryName(path).Name;
                SemanticVersion semVer;
                if (SemanticVersion.TryParse(versionString, out semVer))
                {
                    return(semVer);
                }
                else
                {
                    return(new SemanticVersion(0, 0, 0, 0));
                }
            });

            return(maxVersion.ToString());
        }
Beispiel #17
0
        private void ModifyManifestFile(JObject fileObj, string directoryPath)
        {
            //Get all files in this directory
            string[] filePaths = FileSystemHelpers.GetFiles(directoryPath, "*");

            foreach (string filePath in filePaths)
            {
                //Get last modified timestamp of this file
                String timeString = FileSystemHelpers.GetDirectoryLastWriteTimeUtc(filePath).ToString();
                //Add it as an entry into the manifest
                fileObj.Add(filePath, timeString);
            }

            //Get all child directories of this directory
            string[] direcPaths = FileSystemHelpers.GetDirectories(directoryPath);
            //Do a recursive call to add files of child directories to manifest
            foreach (string direcPath in direcPaths)
            {
                ModifyManifestFile(fileObj, direcPath);
            }
        }
Beispiel #18
0
        private bool IsPreCompiledFunctionApp()
        {
            bool isPrecompiled = false;

            foreach (var directory in FileSystemHelpers.GetDirectories(Environment.CurrentDirectory))
            {
                var functionMetadataFile = Path.Combine(directory, Constants.FunctionJsonFileName);
                if (File.Exists(functionMetadataFile))
                {
                    var    functionMetadataFileContent = FileSystemHelpers.ReadAllTextFromFile(functionMetadataFile);
                    var    functionMetadata            = JsonConvert.DeserializeObject <FunctionMetadata>(functionMetadataFileContent);
                    string extension = Path.GetExtension(functionMetadata?.ScriptFile)?.ToLowerInvariant().TrimStart('.');
                    isPrecompiled = isPrecompiled || (!string.IsNullOrEmpty(extension) && extension == "dll");
                }
                if (isPrecompiled)
                {
                    break;
                }
            }
            return(isPrecompiled);
        }
Beispiel #19
0
        private static void SetPreInstalledExtensionInfo(SiteExtensionInfo info)
        {
            try
            {
                string directory = GetPreInstalledDirectory(info.Id);

                if (info.Type == SiteExtensionInfo.SiteExtensionType.PreInstalledNonKudu)
                {
                    IEnumerable <string> pathStrings = FileSystemHelpers.GetDirectories(directory);

                    SemanticVersion maxVersion = pathStrings.Max(path =>
                    {
                        string versionString = FileSystemHelpers.DirectoryInfoFromDirectoryName(path).Name;
                        SemanticVersion semVer;
                        if (SemanticVersion.TryParse(versionString, out semVer))
                        {
                            return(semVer);
                        }
                        else
                        {
                            return(new SemanticVersion(0, 0, 0, 0));
                        }
                    });

                    info.Version = maxVersion.ToString();
                }
                else if (info.Type == SiteExtensionInfo.SiteExtensionType.PreInstalledKuduModule)
                {
                    info.Version = typeof(SiteExtensionManager).Assembly.GetName().Version.ToString();
                }
            }
            catch (IOException)
            {
                info.Version = null;
            }

            info.LocalIsLatestVersion = true;
        }
Beispiel #20
0
        public static void PurgeOldDeploymentsIfNecessary(string deploymentsPath, ITracer tracer, int totalAllowedDeployments)
        {
            IEnumerable <string> deploymentNames = FileSystemHelpers.GetDirectories(deploymentsPath);

            if (deploymentNames.Count() > totalAllowedDeployments)
            {
                // Order the files in descending order of the modified date and remove the last (N - allowed zip files).
                var deploymentsToDelete = deploymentNames.OrderByDescending(fileName => FileSystemHelpers.GetLastWriteTimeUtc(fileName)).Skip(totalAllowedDeployments);
                foreach (var deploymentName in deploymentsToDelete)
                {
                    using (tracer.Step("Purging old deployment {0}", deploymentName))
                    {
                        try
                        {
                            FileSystemHelpers.DeleteDirectorySafe(deploymentName);
                        }
                        catch (Exception ex)
                        {
                            tracer.TraceError(ex, "Unable to delete deployment {0}", deploymentName);
                        }
                    }
                }
            }
        }
Beispiel #21
0
        internal static void SmartCopy(string sourcePath,
                                       string destinationPath,
                                       Func <string, bool> existsInPrevious,
                                       DirectoryInfoBase sourceDirectory,
                                       DirectoryInfoBase destinationDirectory,
                                       Func <string, DirectoryInfoBase> createDirectoryInfo)
        {
            // Skip source control folder
            if (FileSystemHelpers.IsSourceControlFolder(sourceDirectory))
            {
                return;
            }

            if (!destinationDirectory.Exists)
            {
                destinationDirectory.Create();
            }

            // var previousFilesLookup = GetFiles(previousDirectory);
            var destFilesLookup   = FileSystemHelpers.GetFiles(destinationDirectory);
            var sourceFilesLookup = FileSystemHelpers.GetFiles(sourceDirectory);

            foreach (var destFile in destFilesLookup.Values)
            {
                // If the file doesn't exist in the source, only delete if:
                // 1. We have no previous directory
                // 2. We have a previous directory and the file exists there

                // Trim the start path
                string previousPath = destFile.FullName.Substring(destinationPath.Length).TrimStart('\\');
                if (!sourceFilesLookup.ContainsKey(destFile.Name) &&
                    ((existsInPrevious == null) ||
                     (existsInPrevious != null &&
                      existsInPrevious(previousPath))))
                {
                    destFile.Delete();
                }
            }

            foreach (var sourceFile in sourceFilesLookup.Values)
            {
                // Skip the .deployment file
                if (sourceFile.Name.Equals(DeploymentSettingsProvider.DeployConfigFile, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }


                // if the file exists in the destination then only copy it again if it's
                // last write time is different than the same file in the source (only if it changed)
                FileInfoBase targetFile;
                if (destFilesLookup.TryGetValue(sourceFile.Name, out targetFile) &&
                    sourceFile.LastWriteTimeUtc == targetFile.LastWriteTimeUtc)
                {
                    continue;
                }

                // Otherwise, copy the file
                string path = FileSystemHelpers.GetDestinationPath(sourcePath, destinationPath, sourceFile);

                OperationManager.Attempt(() => sourceFile.CopyTo(path, overwrite: true));
            }

            var sourceDirectoryLookup = FileSystemHelpers.GetDirectories(sourceDirectory);
            var destDirectoryLookup   = FileSystemHelpers.GetDirectories(destinationDirectory);

            foreach (var destSubDirectory in destDirectoryLookup.Values)
            {
                // If the directory doesn't exist in the source, only delete if:
                // 1. We have no previous directory
                // 2. We have a previous directory and the file exists there

                string previousPath = destSubDirectory.FullName.Substring(destinationPath.Length).TrimStart('\\');
                if (!sourceDirectoryLookup.ContainsKey(destSubDirectory.Name) &&
                    ((existsInPrevious == null) ||
                     (existsInPrevious != null &&
                      existsInPrevious(previousPath))))
                {
                    destSubDirectory.Delete(recursive: true);
                }
            }

            foreach (var sourceSubDirectory in sourceDirectoryLookup.Values)
            {
                DirectoryInfoBase targetSubDirectory;
                if (!destDirectoryLookup.TryGetValue(sourceSubDirectory.Name, out targetSubDirectory))
                {
                    string path = FileSystemHelpers.GetDestinationPath(sourcePath, destinationPath, sourceSubDirectory);
                    targetSubDirectory = createDirectoryInfo(path);
                }

                // Sync all sub directories
                SmartCopy(sourcePath, destinationPath, existsInPrevious, sourceSubDirectory, targetSubDirectory, createDirectoryInfo);
            }
        }
Beispiel #22
0
        internal static async Task CheckNonOptionalSettings(IEnumerable <KeyValuePair <string, string> > secrets, string scriptPath)
        {
            try
            {
                // FirstOrDefault returns a KeyValuePair<string, string> which is a struct so it can't be null.
                var azureWebJobsStorage = secrets.FirstOrDefault(pair => pair.Key.Equals("AzureWebJobsStorage", StringComparison.OrdinalIgnoreCase)).Value;
                var functionJsonFiles   = await FileSystemHelpers
                                          .GetDirectories(scriptPath)
                                          .Select(d => Path.Combine(d, "function.json"))
                                          .Where(FileSystemHelpers.FileExists)
                                          .Select(async f => (filePath: f, content: await FileSystemHelpers.ReadAllTextFromFileAsync(f)))
                                          .WhenAll();

                var functionsJsons = functionJsonFiles
                                     .Select(t => (filePath: t.filePath, jObject: JsonConvert.DeserializeObject <JObject>(t.content)))
                                     .Where(b => b.jObject["bindings"] != null);

                var allHttpTrigger = functionsJsons
                                     .Select(b => b.jObject["bindings"])
                                     .SelectMany(i => i)
                                     .Where(b => b?["type"] != null)
                                     .Select(b => b["type"].ToString())
                                     .Where(b => b.IndexOf("Trigger") != -1)
                                     .All(t => t == "httpTrigger");

                if (string.IsNullOrWhiteSpace(azureWebJobsStorage) && !allHttpTrigger)
                {
                    throw new CliException($"Missing value for AzureWebJobsStorage in {SecretsManager.AppSettingsFileName}. This is required for all triggers other than HTTP. "
                                           + $"You can run 'func azure functionapp fetch-app-settings <functionAppName>' or specify a connection string in {SecretsManager.AppSettingsFileName}.");
                }

                foreach ((var filePath, var functionJson) in functionsJsons)
                {
                    foreach (JObject binding in functionJson["bindings"])
                    {
                        foreach (var token in binding)
                        {
                            if (token.Key == "connection" || token.Key == "apiKey" || token.Key == "accountSid" || token.Key == "authToken")
                            {
                                var appSettingName = token.Value.ToString();
                                if (string.IsNullOrWhiteSpace(appSettingName))
                                {
                                    ColoredConsole.WriteLine(WarningColor($"Warning: '{token.Key}' property in '{filePath}' is empty."));
                                }
                                else if (!secrets.Any(v => v.Key.Equals(appSettingName, StringComparison.OrdinalIgnoreCase)))
                                {
                                    ColoredConsole
                                    .WriteLine(WarningColor($"Warning: Cannot find value named '{appSettingName}' in {SecretsManager.AppSettingsFileName} that matches '{token.Key}' property set on '{binding["type"]?.ToString()}' in '{filePath}'. " +
                                                            $"You can run 'func azure functionapp fetch-app-settings <functionAppName>' or specify a connection string in {SecretsManager.AppSettingsFileName}."));
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception e) when(!(e is CliException))
            {
                ColoredConsole.WriteLine(WarningColor($"Warning: unable to verify all settings from {SecretsManager.AppSettingsFileName} and function.json files."));
                if (StaticSettings.IsDebug)
                {
                    ColoredConsole.WriteLine(e);
                }
            }
        }
Beispiel #23
0
        /// <summary>
        /// Mark public for testing
        /// </summary>
        public IList <string> GetPostBuildActionScripts()
        {
            List <string> scriptFilesGroupedAndSorted = new List <string>();
            List <string> scriptFolders = new List <string>();

            const string extensionEnvVarSuffix = "_EXTENSION_VERSION";

            // "/site/deployments/tools/PostDeploymentActions" (can override with %SCM_POST_DEPLOYMENT_ACTIONS_PATH%)
            // if %SCM_POST_DEPLOYMENT_ACTIONS_PATH% is set, we will support both absolute path or relative parth from "d:/home/site/repository"
            var customPostDeploymentPath = DeploymentSettings.GetValue(SettingsKeys.PostDeploymentActionsDirectory);
            var postDeploymentPath       = string.IsNullOrEmpty(customPostDeploymentPath) ? Path.Combine(Environment.DeploymentToolsPath, PostDeploymentActions) : Path.Combine(Environment.RepositoryPath, customPostDeploymentPath);

            if (FileSystemHelpers.DirectoryExists(postDeploymentPath))
            {
                scriptFolders.Add(postDeploymentPath);
            }

            // D:\Program Files (x86)\SiteExtensions
            string siteExtensionFolder = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86), "SiteExtensions");

            // Find all enviroment variable with format {package id}_EXTENSION_VERSION,
            // And find scripts from PostDeploymentActions" folder
            foreach (DictionaryEntry entry in System.Environment.GetEnvironmentVariables())
            {
                string       key = entry.Key.ToString();
                string       val = entry.Value.ToString();
                NuGetVersion ver = null;
                if (key.EndsWith(extensionEnvVarSuffix, StringComparison.OrdinalIgnoreCase) &&
                    (string.Equals("latest", val, StringComparison.OrdinalIgnoreCase) || NuGetVersion.TryParse(val, out ver)))      // either latest or a specific version
                {
                    string extensionName = key.Substring(0, key.Length - extensionEnvVarSuffix.Length);
                    if (ver != null)
                    {
                        // "D:\Program Files (x86)\SiteExtensions", "{ExtensionName}", "{version}", "PostDeploymentActions"
                        //  => D:\Program Files (x86)\SiteExtensions\{ExtensionName}\{version}\PostDeploymentActions
                        string scriptFolder = Path.Combine(siteExtensionFolder, extensionName, ver.ToNormalizedString(), PostDeploymentActions);
                        if (FileSystemHelpers.DirectoryExists(scriptFolder))
                        {
                            scriptFolders.Add(scriptFolder);
                        }
                    }
                    else
                    {
                        // Get the latest version
                        // "D:\Program Files (x86)\SiteExtensions", "{PackageName}"
                        //  => D:\Program Files (x86)\SiteExtensions\{PackageName}
                        string packageRoot = Path.Combine(siteExtensionFolder, extensionName);
                        if (FileSystemHelpers.DirectoryExists(packageRoot))
                        {
                            string[] allVersions = FileSystemHelpers.GetDirectories(packageRoot);   // expecting a list of version e.g D:\Program Files (x86)\SiteExtensions\{PackageName}\{version}
                            if (allVersions.Count() > 0)
                            {
                                // latest version comes first
                                Array.Sort(allVersions, (string v1, string v2) =>
                                {
                                    NuGetVersion ver1 = NuGetVersion.Parse(new DirectoryInfo(v1).Name);
                                    NuGetVersion ver2 = NuGetVersion.Parse(new DirectoryInfo(v2).Name);
                                    return(ver2.CompareTo(ver1));
                                });

                                // "D:\Program Files (x86)\SiteExtensions\{PackageName}\{version}", "PostDeploymentActions"
                                // => D:\Program Files (x86)\SiteExtensions\{PackageName}\{version}\PostDeploymentActions
                                string scriptFolder = Path.Combine(allVersions[0], PostDeploymentActions);
                                if (FileSystemHelpers.DirectoryExists(scriptFolder))
                                {
                                    scriptFolders.Add(scriptFolder);
                                }
                            }
                        }
                    }
                }
            }

            // Find all post action scripts and order file alphabetically for each folder
            foreach (var sf in scriptFolders)
            {
                var files = FileSystemHelpers.GetFiles(sf, "*")
                            .Where(f => f.EndsWith(".cmd", StringComparison.OrdinalIgnoreCase) ||
                                   f.EndsWith(".sh", StringComparison.OrdinalIgnoreCase) ||
                                   f.EndsWith(".bat", StringComparison.OrdinalIgnoreCase) ||
                                   f.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase)).ToList();

                files.Sort();
                scriptFilesGroupedAndSorted.AddRange(files);
            }

            return(scriptFilesGroupedAndSorted);
        }