Skip to content

Commit

Permalink
Simplify using the commands for deployment
Browse files Browse the repository at this point in the history
In case a password was not supplied, or the stored password does not work anymore, do not require the user to start the deploy command from scratch. Instead, prompt for entering a password directly.
  • Loading branch information
Viir committed May 28, 2020
1 parent 888af12 commit 3b7f24f
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1190,8 +1190,9 @@ public void tooling_supports_deploy_app_directly_on_process_store()
var deployReport = elm_fullstack.Program.deployApp(
sourcePath: "./../../../../../example-apps/docker-image-default-app",
site: testDirectory,
sitePassword: null,
initElmAppState: true);
siteDefaultPassword: null,
initElmAppState: true,
promptForPasswordOnConsole: false);

using (var restoredProcess =
Kalmit.PersistentProcess.WebHost.PersistentProcess.PersistentProcessVolatileRepresentation.Restore(
Expand Down
196 changes: 122 additions & 74 deletions implement/elm-fullstack/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,9 @@ CommandOption verboseLogOptionFromCommand(CommandLineApplication command) =>
deployApp(
sourcePath: fromOption.Value(),
site: site,
sitePassword: sitePassword,
initElmAppState: initElmAppStateOption.HasValue());
siteDefaultPassword: sitePassword,
initElmAppState: initElmAppStateOption.HasValue(),
promptForPasswordOnConsole: true);

writeReportToFileInReportDirectory(
reportContent: Newtonsoft.Json.JsonConvert.SerializeObject(deployReport, Newtonsoft.Json.Formatting.Indented),
Expand All @@ -252,8 +253,9 @@ CommandOption verboseLogOptionFromCommand(CommandLineApplication command) =>
var attemptReport =
setElmAppState(
site: site,
sitePassword: sitePassword,
sourcePath: fromOption.Value());
siteDefaultPassword: sitePassword,
sourcePath: fromOption.Value(),
promptForPasswordOnConsole: true);

writeReportToFileInReportDirectory(
reportContent: Newtonsoft.Json.JsonConvert.SerializeObject(attemptReport, Newtonsoft.Json.Formatting.Indented),
Expand Down Expand Up @@ -416,8 +418,9 @@ public class ResponseFromServerStruct
static public DeployAppReport deployApp(
string sourcePath,
string site,
string sitePassword,
bool initElmAppState)
string siteDefaultPassword,
bool initElmAppState,
bool promptForPasswordOnConsole)
{
var beginTime = CommonConversion.TimeStringViewForReport(DateTimeOffset.UtcNow);

Expand Down Expand Up @@ -449,52 +452,53 @@ static public DeployAppReport deployApp(

if (Regex.IsMatch(site, "^http(|s)\\:"))
{
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(
Kalmit.PersistentProcess.WebHost.Configuration.BasicAuthenticationForAdmin(sitePassword))));

var deployAddress =
(site.TrimEnd('/')) +
(initElmAppState
?
StartupAdminInterface.PathApiDeployAppConfigAndInitElmAppState
:
StartupAdminInterface.PathApiDeployAppConfigAndMigrateElmAppState);

Console.WriteLine("Beginning to deploy app '" + appConfigBuildId + "' to '" + deployAddress + "'...");
var deployAddress =
(site.TrimEnd('/')) +
(initElmAppState
?
StartupAdminInterface.PathApiDeployAppConfigAndInitElmAppState
:
StartupAdminInterface.PathApiDeployAppConfigAndMigrateElmAppState);

var httpContent = new System.Net.Http.ByteArrayContent(appConfigZipArchive);
Console.WriteLine("Attempting to deploy app '" + appConfigBuildId + "' to '" + deployAddress + "'...");

httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/zip");
httpContent.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = appConfigBuildId + ".zip" };
var httpResponse = AttemptHttpRequest(() =>
{
var httpContent = new System.Net.Http.ByteArrayContent(appConfigZipArchive);

var httpResponse = httpClient.PostAsync(deployAddress, httpContent).Result;
httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/zip");
httpContent.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = appConfigBuildId + ".zip" };

var responseContentString = httpResponse.Content.ReadAsStringAsync().Result;
return new System.Net.Http.HttpRequestMessage
{
Method = System.Net.Http.HttpMethod.Post,
RequestUri = new Uri(deployAddress),
Content = httpContent,
};
},
defaultPassword: siteDefaultPassword,
promptForPasswordOnConsole: promptForPasswordOnConsole).Result;

Console.WriteLine(
"Server response: " + httpResponse.StatusCode + "\n" +
responseContentString);
var responseContentString = httpResponse.Content.ReadAsStringAsync().Result;

object responseBodyReport = responseContentString;
Console.WriteLine(
"Server response: " + httpResponse.StatusCode + "\n" + responseContentString);

try
{
responseBodyReport =
Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(responseContentString);
}
catch { }
object responseBodyReport = responseContentString;

responseFromServer = new DeployAppReport.ResponseFromServerStruct
{
statusCode = (int)httpResponse.StatusCode,
body = responseBodyReport,
};
try
{
responseBodyReport =
Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>((string)responseBodyReport);
}
catch { }

responseFromServer = new DeployAppReport.ResponseFromServerStruct
{
statusCode = (int)httpResponse.StatusCode,
body = responseBodyReport,
};
}
else
{
Expand Down Expand Up @@ -548,6 +552,45 @@ static public DeployAppReport deployApp(
};
}

static async System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>
AttemptHttpRequest(
Func<System.Net.Http.HttpRequestMessage> buildRequest,
string defaultPassword,
bool promptForPasswordOnConsole)
{
using (var httpClient = new System.Net.Http.HttpClient())
{
void setHttpClientPassword(string password)
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(
Kalmit.PersistentProcess.WebHost.Configuration.BasicAuthenticationForAdmin(password))));
}

setHttpClientPassword(defaultPassword);

var httpResponse = await httpClient.SendAsync(buildRequest());

if (promptForPasswordOnConsole &&
httpResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized &&
httpResponse.Headers.WwwAuthenticate.Any())
{
Console.WriteLine("The server at '" + httpResponse.RequestMessage.RequestUri.ToString() + "' is asking for authentication. Please enter the password we should use to authenticate there:");

var password = ReadLine.ReadPassword("> ").Trim();

Console.WriteLine("I retry using this password...");

setHttpClientPassword(password);

httpResponse = await httpClient.SendAsync(buildRequest());
}

return httpResponse;
}
}

class SetElmAppStateReport
{
public string beginTime;
Expand All @@ -570,7 +613,11 @@ public class ResponseFromServerStruct
}
}

static SetElmAppStateReport setElmAppState(string site, string sitePassword, string sourcePath)
static SetElmAppStateReport setElmAppState(
string site,
string siteDefaultPassword,
string sourcePath,
bool promptForPasswordOnConsole)
{
var beginTime = CommonConversion.TimeStringViewForReport(DateTimeOffset.UtcNow);

Expand All @@ -586,41 +633,42 @@ static SetElmAppStateReport setElmAppState(string site, string sitePassword, str

SetElmAppStateReport.ResponseFromServerStruct responseFromServer = null;

using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(
Kalmit.PersistentProcess.WebHost.Configuration.BasicAuthenticationForAdmin(sitePassword))));

var httpContent = new System.Net.Http.ByteArrayContent(elmAppStateSerialized);

httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var httpResponse = AttemptHttpRequest(() =>
{
var httpContent = new System.Net.Http.ByteArrayContent(elmAppStateSerialized);

var httpResponse = httpClient.PostAsync(
site.TrimEnd('/') + StartupAdminInterface.PathApiElmAppState, httpContent).Result;
httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

var responseContentString = httpResponse.Content.ReadAsStringAsync().Result;
return new System.Net.Http.HttpRequestMessage
{
Method = System.Net.Http.HttpMethod.Post,
RequestUri = new Uri(site.TrimEnd('/') + StartupAdminInterface.PathApiElmAppState),
Content = httpContent,
};
},
defaultPassword: siteDefaultPassword,
promptForPasswordOnConsole: promptForPasswordOnConsole).Result;

Console.WriteLine(
"Server response: " + httpResponse.StatusCode + "\n" +
responseContentString);
var responseContentString = httpResponse.Content.ReadAsStringAsync().Result;

object responseBodyReport = responseContentString;
Console.WriteLine(
"Server response: " + httpResponse.StatusCode + "\n" +
responseContentString);

try
{
responseBodyReport =
Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(responseContentString);
}
catch { }
object responseBodyReport = responseContentString;

responseFromServer = new SetElmAppStateReport.ResponseFromServerStruct
{
statusCode = (int)httpResponse.StatusCode,
body = responseBodyReport,
};
try
{
responseBodyReport =
Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>((string)responseBodyReport);
}
catch { }

responseFromServer = new SetElmAppStateReport.ResponseFromServerStruct
{
statusCode = (int)httpResponse.StatusCode,
body = responseBodyReport,
};

return new SetElmAppStateReport
{
Expand Down Expand Up @@ -838,8 +886,8 @@ string getCurrentValueOfEnvironmentVariable() =>
// https://docs.microsoft.com/en-us/previous-versions//cc723564(v=technet.10)?redirectedfrom=MSDN#XSLTsection127121120120

Console.WriteLine(
"I added the path '" + executableDirectoryPath + "' to the '" + environmentVariableName +
"' environment variable for the current user account. You will be able to use the '" + commandName + "' command in newer instances of the Command Prompt.");
"I added the path '" + executableDirectoryPath + "' to the '" + environmentVariableName +
"' environment variable for the current user account. You will be able to use the '" + commandName + "' command in newer instances of the Command Prompt.");
});

var executableIsRegisteredOnPath =
Expand Down
1 change: 1 addition & 0 deletions implement/elm-fullstack/elm-fullstack.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

<ItemGroup>
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="3.0.0" />
<PackageReference Include="ReadLine" Version="2.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 3b7f24f

Please sign in to comment.