Merge pull request #4080 from umbraco/temp8-auto-install
install for Deploy
This commit is contained in:
@@ -76,11 +76,13 @@ namespace Umbraco.Core.Components
|
||||
var composerTypeList = _composerTypes
|
||||
.Where(x =>
|
||||
{
|
||||
// use the min level specified by the attribute if any
|
||||
// otherwise, user composers have Run min level, anything else is Unknown (always run)
|
||||
// use the min/max levels specified by the attribute if any
|
||||
// otherwise, min: user composers are Run, anything else is Unknown (always run)
|
||||
// max: everything is Run (always run)
|
||||
var attr = x.GetCustomAttribute<RuntimeLevelAttribute>();
|
||||
var minLevel = attr?.MinLevel ?? (x.Implements<IUserComposer>() ? RuntimeLevel.Run : RuntimeLevel.Unknown);
|
||||
return _composition.RuntimeState.Level >= minLevel;
|
||||
var maxLevel = attr?.MaxLevel ?? RuntimeLevel.Run;
|
||||
return _composition.RuntimeState.Level >= minLevel && _composition.RuntimeState.Level <= maxLevel;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
using System;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks a composer to indicate a minimum and/or maximum runtime level for which the composer would compose.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class /*, AllowMultiple = false, Inherited = true*/)]
|
||||
public class RuntimeLevelAttribute : Attribute
|
||||
{
|
||||
//public RuntimeLevelAttribute()
|
||||
//{ }
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum runtime level for which the composer would compose.
|
||||
/// </summary>
|
||||
public RuntimeLevel MinLevel { get; set; } = RuntimeLevel.Install;
|
||||
|
||||
public RuntimeLevel MinLevel { get; set; } = RuntimeLevel.Boot;
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum runtime level for which the composer would compose.
|
||||
/// </summary>
|
||||
public RuntimeLevel MaxLevel { get; set; } = RuntimeLevel.Run;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,11 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
RuntimeLevel Level { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reason for the runtime level of execution.
|
||||
/// </summary>
|
||||
RuntimeLevelReason Reason { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current migration state.
|
||||
/// </summary>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
/// <summary>
|
||||
/// Creates the initial database schema during install.
|
||||
/// </summary>
|
||||
internal class DatabaseSchemaCreator
|
||||
public class DatabaseSchemaCreator
|
||||
{
|
||||
private readonly IUmbracoDatabase _database;
|
||||
private readonly ILogger _logger;
|
||||
@@ -28,7 +28,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
private ISqlSyntaxProvider SqlSyntax => _database.SqlContext.SqlSyntax;
|
||||
|
||||
// all tables, in order
|
||||
public static readonly List<Type> OrderedTables = new List<Type>
|
||||
internal static readonly List<Type> OrderedTables = new List<Type>
|
||||
{
|
||||
typeof (UserDto),
|
||||
typeof (NodeDto),
|
||||
@@ -138,7 +138,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
/// <summary>
|
||||
/// Validates the schema of the current database.
|
||||
/// </summary>
|
||||
public DatabaseSchemaResult ValidateSchema()
|
||||
internal DatabaseSchemaResult ValidateSchema()
|
||||
{
|
||||
var result = new DatabaseSchemaResult(SqlSyntax);
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
|
||||
/// attribute will be used for the table name. If the attribute is not present, the name
|
||||
/// <typeparamref name="T"/> will be used instead.
|
||||
///
|
||||
///
|
||||
/// If a table with the same name already exists, the <paramref name="overwrite"/> parameter will determine
|
||||
/// whether the table is overwritten. If <c>true</c>, the table will be overwritten, whereas this method will
|
||||
/// not do anything if the parameter is <c>false</c>.
|
||||
@@ -409,14 +409,14 @@ namespace Umbraco.Core.Migrations.Install
|
||||
/// If <paramref name="modelType"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from
|
||||
/// that attribute will be used for the table name. If the attribute is not present, the name
|
||||
/// <paramref name="modelType"/> will be used instead.
|
||||
///
|
||||
///
|
||||
/// If a table with the same name already exists, the <paramref name="overwrite"/> parameter will determine
|
||||
/// whether the table is overwritten. If <c>true</c>, the table will be overwritten, whereas this method will
|
||||
/// not do anything if the parameter is <c>false</c>.
|
||||
///
|
||||
/// This need to execute as part of a transaction.
|
||||
/// </remarks>
|
||||
public void CreateTable(bool overwrite, Type modelType, DatabaseDataCreator dataCreation)
|
||||
internal void CreateTable(bool overwrite, Type modelType, DatabaseDataCreator dataCreation)
|
||||
{
|
||||
if (!_database.InTransaction)
|
||||
throw new InvalidOperationException("Database is not in a transaction.");
|
||||
|
||||
@@ -18,6 +18,12 @@ namespace Umbraco.Core.Persistence
|
||||
/// </summary>
|
||||
bool Configured { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the connection string.
|
||||
/// </summary>
|
||||
/// <remarks>Throws if the factory is not configured.</remarks>
|
||||
string ConnectionString { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the database can connect.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Configuration;
|
||||
using System.Data.Common;
|
||||
using System.Threading;
|
||||
using LightInject;
|
||||
using NPoco;
|
||||
using NPoco.FluentMappings;
|
||||
using Umbraco.Core.Exceptions;
|
||||
@@ -102,6 +103,16 @@ namespace Umbraco.Core.Persistence
|
||||
/// <inheritdoc />
|
||||
public bool Configured { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ConnectionString
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureConfigured();
|
||||
return _connectionString;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanConnect
|
||||
{
|
||||
|
||||
@@ -252,7 +252,7 @@ namespace Umbraco.Core.Runtime
|
||||
{
|
||||
_state.DetermineRuntimeLevel(databaseFactory, profilingLogger);
|
||||
|
||||
profilingLogger.Debug<CoreRuntime>("Runtime level: {RuntimeLevel}", _state.Level);
|
||||
profilingLogger.Debug<CoreRuntime>("Runtime level: {RuntimeLevel} - {RuntimeLevelReason}", _state.Level, _state.Reason);
|
||||
|
||||
if (_state.Level == RuntimeLevel.Upgrade)
|
||||
{
|
||||
@@ -263,6 +263,7 @@ namespace Umbraco.Core.Runtime
|
||||
catch
|
||||
{
|
||||
_state.Level = RuntimeLevel.BootFailed;
|
||||
_state.Reason = RuntimeLevelReason.BootFailedOnException;
|
||||
timer.Fail();
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the levels in which the runtime can run.
|
||||
/// </summary>
|
||||
public enum RuntimeLevel
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
68
src/Umbraco.Core/RuntimeLevelReason.cs
Normal file
68
src/Umbraco.Core/RuntimeLevelReason.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the reason for the runtime level.
|
||||
/// </summary>
|
||||
public enum RuntimeLevelReason
|
||||
{
|
||||
/// <summary>
|
||||
/// The code version is lower than the version indicated in web.config, and
|
||||
/// downgrading Umbraco is not supported.
|
||||
/// </summary>
|
||||
BootFailedCannotDowngrade,
|
||||
|
||||
/// <summary>
|
||||
/// The runtime cannot connect to the configured database.
|
||||
/// </summary>
|
||||
BootFailedCannotConnectToDatabase,
|
||||
|
||||
/// <summary>
|
||||
/// The runtime can connect to the configured database, but it cannot
|
||||
/// retrieve the migrations status.
|
||||
/// </summary>
|
||||
BootFailedCannotCheckUpgradeState,
|
||||
|
||||
/// <summary>
|
||||
/// An exception was thrown during boot.
|
||||
/// </summary>
|
||||
BootFailedOnException,
|
||||
|
||||
/// <summary>
|
||||
/// Umbraco is not installed at all.
|
||||
/// </summary>
|
||||
InstallNoVersion,
|
||||
|
||||
/// <summary>
|
||||
/// A version is specified in web.config but the database is not configured.
|
||||
/// </summary>
|
||||
/// <remarks>This is a weird state.</remarks>
|
||||
InstallNoDatabase,
|
||||
|
||||
/// <summary>
|
||||
/// A version is specified in web.config and a database is configured, but the
|
||||
/// database is missing, and installing over a missing database has been enabled.
|
||||
/// </summary>
|
||||
InstallMissingDatabase,
|
||||
|
||||
/// <summary>
|
||||
/// A version is specified in web.config and a database is configured, but the
|
||||
/// database is empty, and installing over an empty database has been enabled.
|
||||
/// </summary>
|
||||
InstallEmptyDatabase,
|
||||
|
||||
/// <summary>
|
||||
/// Umbraco runs an old version.
|
||||
/// </summary>
|
||||
UpgradeOldVersion,
|
||||
|
||||
/// <summary>
|
||||
/// Umbraco runs the current version but some migrations have not run.
|
||||
/// </summary>
|
||||
UpgradeMigrations,
|
||||
|
||||
/// <summary>
|
||||
/// Umbraco is running.
|
||||
/// </summary>
|
||||
Run
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,9 @@ namespace Umbraco.Core
|
||||
internal set { _level = value; if (value == RuntimeLevel.Run) _runLevel.Set(); }
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public RuntimeLevelReason Reason { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the <see cref="ApplicationUrl"/> property has a value.
|
||||
/// </summary>
|
||||
@@ -143,6 +146,7 @@ namespace Umbraco.Core
|
||||
// there is no local version, we are not installed
|
||||
logger.Debug<RuntimeState>("No local version, need to install Umbraco.");
|
||||
Level = RuntimeLevel.Install;
|
||||
Reason = RuntimeLevelReason.InstallNoVersion;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -152,12 +156,14 @@ namespace Umbraco.Core
|
||||
// need to upgrade
|
||||
logger.Debug<RuntimeState>("Local version '{LocalVersion}' < code version '{CodeVersion}', need to upgrade Umbraco.", localVersion, codeVersion);
|
||||
Level = RuntimeLevel.Upgrade;
|
||||
Reason = RuntimeLevelReason.UpgradeOldVersion;
|
||||
}
|
||||
else if (localVersion > codeVersion)
|
||||
{
|
||||
logger.Warn<RuntimeState>("Local version '{LocalVersion}' > code version '{CodeVersion}', downgrading is not supported.", localVersion, codeVersion);
|
||||
|
||||
// in fact, this is bad enough that we want to throw
|
||||
Reason = RuntimeLevelReason.BootFailedCannotDowngrade;
|
||||
throw new BootFailedException($"Local version \"{localVersion}\" > code version \"{codeVersion}\", downgrading is not supported.");
|
||||
}
|
||||
else if (databaseFactory.Configured == false)
|
||||
@@ -166,16 +172,18 @@ namespace Umbraco.Core
|
||||
// install (again? this is a weird situation...)
|
||||
logger.Debug<RuntimeState>("Database is not configured, need to install Umbraco.");
|
||||
Level = RuntimeLevel.Install;
|
||||
Reason = RuntimeLevelReason.InstallNoDatabase;
|
||||
return;
|
||||
}
|
||||
|
||||
// else, keep going,
|
||||
// anything other than install wants a database - see if we can connect
|
||||
// (since this is an already existing database, assume localdb is ready)
|
||||
for (var i = 0; i < 5; i++)
|
||||
var tries = RuntimeStateOptions.InstallMissingDatabase ? 2 : 5;
|
||||
for (var i = 0;;)
|
||||
{
|
||||
connect = databaseFactory.CanConnect;
|
||||
if (connect) break;
|
||||
if (connect || ++i == tries) break;
|
||||
logger.Debug<RuntimeState>("Could not immediately connect to database, trying again.");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
@@ -185,7 +193,16 @@ namespace Umbraco.Core
|
||||
// cannot connect to configured database, this is bad, fail
|
||||
logger.Debug<RuntimeState>("Could not connect to database.");
|
||||
|
||||
// in fact, this is bad enough that we want to throw
|
||||
if (RuntimeStateOptions.InstallMissingDatabase)
|
||||
{
|
||||
// ok to install on a configured but missing database
|
||||
Level = RuntimeLevel.Install;
|
||||
Reason = RuntimeLevelReason.InstallMissingDatabase;
|
||||
return;
|
||||
}
|
||||
|
||||
// else it is bad enough that we want to throw
|
||||
Reason = RuntimeLevelReason.BootFailedCannotConnectToDatabase;
|
||||
throw new BootFailedException("A connection string is configured but Umbraco could not connect to the database.");
|
||||
}
|
||||
|
||||
@@ -195,7 +212,6 @@ namespace Umbraco.Core
|
||||
|
||||
// else
|
||||
// look for a matching migration entry - bypassing services entirely - they are not 'up' yet
|
||||
// fixme - in a LB scenario, ensure that the DB gets upgraded only once!
|
||||
bool noUpgrade;
|
||||
try
|
||||
{
|
||||
@@ -205,6 +221,17 @@ namespace Umbraco.Core
|
||||
{
|
||||
// can connect to the database but cannot check the upgrade state... oops
|
||||
logger.Warn<RuntimeState>(e, "Could not check the upgrade state.");
|
||||
|
||||
if (RuntimeStateOptions.InstallEmptyDatabase)
|
||||
{
|
||||
// ok to install on an empty database
|
||||
Level = RuntimeLevel.Install;
|
||||
Reason = RuntimeLevelReason.InstallEmptyDatabase;
|
||||
return;
|
||||
}
|
||||
|
||||
// else it is bad enough that we want to throw
|
||||
Reason = RuntimeLevelReason.BootFailedCannotCheckUpgradeState;
|
||||
throw new BootFailedException("Could not check the upgrade state.", e);
|
||||
}
|
||||
|
||||
@@ -216,6 +243,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
// the database version matches the code & files version, all clear, can run
|
||||
Level = RuntimeLevel.Run;
|
||||
Reason = RuntimeLevelReason.Run;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -226,6 +254,7 @@ namespace Umbraco.Core
|
||||
// which means the local files have been upgraded but not the database - need to upgrade
|
||||
logger.Debug<RuntimeState>("Has not reached the final upgrade step, need to upgrade Umbraco.");
|
||||
Level = RuntimeLevel.Upgrade;
|
||||
Reason = RuntimeLevelReason.UpgradeMigrations;
|
||||
}
|
||||
|
||||
protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger)
|
||||
|
||||
40
src/Umbraco.Core/RuntimeStateOptions.cs
Normal file
40
src/Umbraco.Core/RuntimeStateOptions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows configuration of the <see cref="RuntimeState"/> in PreApplicationStart or in appSettings
|
||||
/// </summary>
|
||||
public static class RuntimeStateOptions
|
||||
{
|
||||
// configured statically or via app settings
|
||||
private static bool BoolSetting(string key, bool missing) => ConfigurationManager.AppSettings[key]?.InvariantEquals("true") ?? missing;
|
||||
|
||||
/// <summary>
|
||||
/// If true the RuntimeState will continue the installation sequence when a database is missing
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In this case it will be up to the implementor that is setting this value to true to take over the bootup/installation sequence
|
||||
/// </remarks>
|
||||
public static bool InstallMissingDatabase
|
||||
{
|
||||
get => _installEmptyDatabase ?? BoolSetting("Umbraco.Core.RuntimeState.InstallMissingDatabase", false);
|
||||
set => _installEmptyDatabase = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true the RuntimeState will continue the installation sequence when a database is available but is empty
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In this case it will be up to the implementor that is setting this value to true to take over the bootup/installation sequence
|
||||
/// </remarks>
|
||||
public static bool InstallEmptyDatabase
|
||||
{
|
||||
get => _installMissingDatabase ?? BoolSetting("Umbraco.Core.RuntimeState.InstallEmptyDatabase", false);
|
||||
set => _installMissingDatabase = value;
|
||||
}
|
||||
|
||||
private static bool? _installMissingDatabase;
|
||||
private static bool? _installEmptyDatabase;
|
||||
}
|
||||
}
|
||||
@@ -511,6 +511,8 @@
|
||||
<Compile Include="PropertyEditors\VoidEditor.cs" />
|
||||
<Compile Include="ReadLock.cs" />
|
||||
<Compile Include="ReflectionUtilities-Unused.cs" />
|
||||
<Compile Include="RuntimeLevelReason.cs" />
|
||||
<Compile Include="RuntimeStateOptions.cs" />
|
||||
<Compile Include="Runtime\CoreRuntime.cs" />
|
||||
<Compile Include="Runtime\CoreRuntimeComponent.cs" />
|
||||
<Compile Include="CustomBooleanTypeConverter.cs" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("umbraco.install").factory('installerService', function($rootScope, $q, $timeout, $http, $location, $log){
|
||||
angular.module("umbraco.install").factory('installerService', function ($rootScope, $q, $timeout, $http, $templateRequest){
|
||||
|
||||
var _status = {
|
||||
index: 0,
|
||||
@@ -106,19 +106,26 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
|
||||
//loads the needed steps and sets the intial state
|
||||
init : function(){
|
||||
service.status.loading = true;
|
||||
if(!_status.all){
|
||||
service.getSteps().then(function(response){
|
||||
service.status.steps = response.data.steps;
|
||||
service.status.index = 0;
|
||||
_installerModel.installId = response.data.installId;
|
||||
service.findNextStep();
|
||||
if (!_status.all) {
|
||||
//pre-load the error page, if an error occurs, the page might not be able to load
|
||||
// so we want to make sure it's available in the templatecache first
|
||||
$templateRequest("views/install/error.html").then(x => {
|
||||
service.getSteps().then(response => {
|
||||
service.status.steps = response.data.steps;
|
||||
service.status.index = 0;
|
||||
_installerModel.installId = response.data.installId;
|
||||
service.findNextStep();
|
||||
|
||||
$timeout(function(){
|
||||
service.status.loading = false;
|
||||
service.status.configuring = true;
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
$timeout(function() {
|
||||
service.status.loading = false;
|
||||
service.status.configuring = true;
|
||||
},
|
||||
2000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
//loads available packages from our.umbraco.com
|
||||
|
||||
Reference in New Issue
Block a user