private DatabaseCommandResult DeployFeaturesFromExtensions(IOptions options, UpgradeEngineConfig config)
        {
            var features  = options.Features.ToList();
            var filePaths = options.FilePaths.ToList();

            // if no features or extensions then we just exit with success
            if (!features.Any() || !filePaths.Any())
            {
                _logger.Debug("No features or file paths are found.");
                return(new DatabaseCommandResult {
                    IsSuccessful = true
                });
            }

            string engineTypeDirectory = options.Engine.Directory();

            var commandResults = new List <DatabaseCommandResult>();

            // deploy structure scripts
            // NewVersion:    /Artifacts/[EngineTypeFolder]/Structure/[DatabaseTypeFolder]/[Feature]/{*.sql}
            // LegacyVersion: /Database/Structure/[DatabaseTypeFolder]/[Feature]/{*.sql}
            foreach (string path in filePaths)
            {
                foreach (string feature in features)
                {
                    commandResults.Add(RunScripts(path, feature, true));
                }
            }

            // deploy data scripts
            // NewVersion:    /Artifacts/[EngineTypeFolder]/Data/[DatabaseTypeFolder]/[Feature]/{*.sql}
            // LegacyVersion: /Database/Data/[DatabaseTypeFolder]/[Feature]/{*.sql}
            foreach (string path in filePaths)
            {
                foreach (string feature in features)
                {
                    commandResults.Add(RunScripts(path, feature, false));
                }
            }

            return(DatabaseCommandResult.Create(commandResults));

            DatabaseCommandResult RunScripts(string path, string feature, bool isStructureScripts)
            {
                // note we can only run one path at a time, so we must recreate the db up instance.
                config.ParentPath = path;
                config.ScriptPath = ScriptsPath(new ScriptPathResolver(path, options.DatabaseType, options.Engine, feature));

                if (!Directory.Exists(config.ScriptPath))
                {
                    _logger.Debug($"Feature {feature} is not found in path {config.ScriptPath}");

                    config.ScriptPath = ScriptsPath(new LegacyScriptPathResolver(path, options.DatabaseType, feature));

                    if (!Directory.Exists(config.ScriptPath))
                    {
                        _logger.Debug($"Feature {feature} is not found in path {config.ScriptPath}");
                        return(new DatabaseCommandResult {
                            IsSuccessful = true
                        });
                    }

                    // If config.Path test fails for NewVersion, engine should not be PostgreSql
                    // only if folder exists
                    if (!options.AreFeaturesValidForLegacyDatabaseDirectoryStructure())
                    {
                        _logger.Warn("Currently only SqlServer is supported to deploy features for Legacy versions of Ed-Fi ODS Model");

                        return(new DatabaseCommandResult {
                            IsSuccessful = true
                        });
                    }
                }

                _logger.Info($"Deploying feature {feature} from path {config.ScriptPath}");

                var upgradeEngine = _upgradeEngineFactory.Create(config);

                if (config.PerformWhatIf)
                {
                    return(new DatabaseCommandResult
                    {
                        RequiresUpgrade = upgradeEngine.IsUpgradeRequired(),
                        IsSuccessful = true
                    });
                }

                var result = upgradeEngine.PerformUpgrade();

                return(new DatabaseCommandResult
                {
                    IsSuccessful = result.Successful,
                    Exception = result.Error
                });

                string ScriptsPath(IScriptPathResolver fileInfoProvider)
                => isStructureScripts
                        ? fileInfoProvider.StructureScriptPath()
                        : fileInfoProvider.DataScriptPath();
            }
        }
Example #2
0
        public override bool IsSatisfiedBy(IOptions obj)
        {
            Preconditions.ThrowIfNull(obj, nameof(obj));

            if (!obj.Features.Any())
            {
                return(true);
            }

            var featureExpression = new Regex(@"\d{4}.*?");

            if (obj.Features.Any(f => featureExpression.IsMatch(f)))
            {
                ErrorMessages.Add("Feature names must not start with four digits");
            }

            string engineTypeDirectory = obj.Engine.Directory();

            // to assist in debugging
            if (obj.FilePaths.Any())
            {
                foreach (string feature in obj.Features)
                {
                    foreach (string path in obj.FilePaths)
                    {
                        TestFeatureDirectory(path, DatabaseConventions.StructureDirectory, feature);

                        TestFeatureDirectory(path, DatabaseConventions.DataDirectory, feature);
                    }
                }
            }

            return(!ErrorMessages.Any());

            void TestFeatureDirectory(string path, string structureOrDataDirectory, string feature)
            {
                string databaseTypeDirectory = obj.DatabaseType.Directory(ArtifactsFolderStructureType.NewVersion);

                string featurePath = Path.GetFullPath(
                    Path.Combine(
                        path,
                        DatabaseConventions.ArtifactsDirectory,
                        engineTypeDirectory,
                        structureOrDataDirectory,
                        databaseTypeDirectory,
                        feature));

                if (!Directory.Exists(featurePath))
                {
                    _logger.Debug($"Feature {structureOrDataDirectory} {feature} does not exist in path {path}");

                    databaseTypeDirectory = obj.DatabaseType.Directory(ArtifactsFolderStructureType.LegacyVersion);

                    featurePath = Path.GetFullPath(
                        Path.Combine(
                            path,
                            DatabaseConventions.DatabaseDirectory,
                            structureOrDataDirectory,
                            databaseTypeDirectory,
                            feature));

                    if (!Directory.Exists(featurePath))
                    {
                        _logger.Debug($"Feature {structureOrDataDirectory} {feature} does not exist in path {path}");
                    }

                    // If config.Path test fails for v3.3, engine should not be PostgreSql
                    // only if folder exists
                    if (!obj.AreFeaturesValidForLegacyDatabaseDirectoryStructure())
                    {
                        _logger.Debug("Currently only SqlServer is supported to deploy features for Ed-Fi ODS/API.");
                    }
                }
            }
        }