Skip to content

Commit

Permalink
Begin implementation of Enterprise ManagementConsole API, redux (#2010)
Browse files Browse the repository at this point in the history
* Initial implementation of ManagementConsole - maintenance mode

* Add environment var support for management console password for integration tests

* Add reactive client and unit tests

* Update some xmlDoc

* I think this is a better way to setup the underlying baseUri on IConneciton, to achieve managemet console access rather than requiring a specific GitHubClient that cant call normal API's
Instead, the management client methods can check the base Url and if it contains /api/v3/ they can set their relative endpoint Uri to include a leading "/" which will cause the /api/v3/ to be removed.

* Update EnterpriseClient.cs

Fix xml comments

* Update IEnterpriseClient.cs

Fix xml comments

* Still trying to get the xmDoc perfect, thanks app veyor :)

* XmlDoc'ing my way to success

* Add specific test attribute for management console tests

* check chronic string empty/null

* Use helper's password field in test

* Tidy up maintenance mode tests by using a context/destructor to manage the initial/end state of maintenance mode

* make internal and tidy up URL concatenation

* move GHE endpoint fixup inside ApiUrls methods

* Rework request object to be the correct structure so SimpleJsonSerializer can be used to serialize it.  Remove MaintenanceDate class and just pass in the Date/string for when
Still need to use UrlFormEncoding rather than json in the POST body though...

* Create abstract base class for FormUrlEncoded parameters (similar to existing RequetParameters) and inherit from it in UpdateMaintenanceRequest

* Fix maintenance context logic - destructor should always turn maintenance OFF regardless of initial requested state

* Fix xml comment

* Fix Xml comment

* Those pesky xml comments!

* Fine, I give up!

* Fix string.Format

* fix bad rebase

* fix failing convention tests

* restore missing whitespace

* writing some docs

* some edits

* edit
  • Loading branch information
shiftkey authored Sep 22, 2019
1 parent fafbf33 commit 8cd0b34
Show file tree
Hide file tree
Showing 37 changed files with 965 additions and 40 deletions.
18 changes: 13 additions & 5 deletions Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,47 @@ public interface IObservableEnterpriseClient
/// </summary>
/// <remarks>
/// See the <a href="http://developer.github.com/v3/enterprise/admin_stats/">Enterprise Admin Stats API documentation</a> for more information.
///</remarks>
/// </remarks>
IObservableEnterpriseAdminStatsClient AdminStats { get; }

/// <summary>
/// A client for GitHub's Enterprise LDAP API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/ldap/">Enterprise LDAP API documentation</a> for more information.
///</remarks>
/// </remarks>
IObservableEnterpriseLdapClient Ldap { get; }

/// <summary>
/// A client for GitHub's Enterprise License API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/license/">Enterprise License API documentation</a> for more information.
///</remarks>
/// </remarks>
IObservableEnterpriseLicenseClient License { get; }

/// <summary>
/// A client for GitHub's Enterprise Management Console API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/management_console/">Enterprise Management Console API documentation</a> for more information.
/// </remarks>
IObservableEnterpriseManagementConsoleClient ManagementConsole { get; }

/// <summary>
/// A client for GitHub's Enterprise Organization API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/orgs/">Enterprise Organization API documentation</a> for more information.
///</remarks>
/// </remarks>
IObservableEnterpriseOrganizationClient Organization { get; }

/// <summary>
/// A client for GitHub's Enterprise Search Indexing API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/search_indexing/">Enterprise Search Indexing API documentation</a> for more information.
///</remarks>
/// </remarks>
IObservableEnterpriseSearchIndexingClient SearchIndexing { get; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Diagnostics.CodeAnalysis;

namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's Enterprise Management Console API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/management_console/">Enterprise Management Console API documentation</a> for more information.
/// </remarks>
public interface IObservableEnterpriseManagementConsoleClient
{
/// <summary>
/// Gets GitHub Enterprise Maintenance Mode Status
/// </summary>
/// <remarks>
/// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status
/// </remarks>
/// <returns>The <see cref="MaintenanceModeResponse"/>.</returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
IObservable<MaintenanceModeResponse> GetMaintenanceMode(string managementConsolePassword);

/// <summary>
/// Sets GitHub Enterprise Maintenance Mode
/// </summary>
/// <remarks>
/// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status
/// </remarks>
/// <returns>The <see cref="MaintenanceModeResponse"/>.</returns>
IObservable<MaintenanceModeResponse> EditMaintenanceMode(UpdateMaintenanceRequest maintenance, string managementConsolePassword);
}
}
19 changes: 14 additions & 5 deletions Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public ObservableEnterpriseClient(IGitHubClient client)
AdminStats = new ObservableEnterpriseAdminStatsClient(client);
Ldap = new ObservableEnterpriseLdapClient(client);
License = new ObservableEnterpriseLicenseClient(client);
ManagementConsole = new ObservableEnterpriseManagementConsoleClient(client);
Organization = new ObservableEnterpriseOrganizationClient(client);
SearchIndexing = new ObservableEnterpriseSearchIndexingClient(client);
PreReceiveEnvironment = new ObservableEnterprisePreReceiveEnvironmentsClient(client);
Expand All @@ -25,39 +26,47 @@ public ObservableEnterpriseClient(IGitHubClient client)
/// </summary>
/// <remarks>
/// See the <a href="http://developer.github.com/v3/enterprise/admin_stats/">Enterprise Admin Stats API documentation</a> for more information.
///</remarks>
/// </remarks>
public IObservableEnterpriseAdminStatsClient AdminStats { get; private set; }

/// <summary>
/// A client for GitHub's Enterprise LDAP API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/ldap/">Enterprise LDAP API documentation</a> for more information.
///</remarks>
/// </remarks>
public IObservableEnterpriseLdapClient Ldap { get; private set; }

/// <summary>
/// A client for GitHub's Enterprise License API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/license/">Enterprise License API documentation</a> for more information.
///</remarks>
/// </remarks>
public IObservableEnterpriseLicenseClient License { get; private set; }

/// <summary>
/// A client for GitHub's Enterprise Management Console API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/management_console/">Enterprise Management Console API documentation</a> for more information.
/// </remarks>
public IObservableEnterpriseManagementConsoleClient ManagementConsole { get; private set; }

/// <summary>
/// A client for GitHub's Enterprise Organization API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/orgs/">Enterprise Organization API documentation</a> for more information.
///</remarks>
/// </remarks>
public IObservableEnterpriseOrganizationClient Organization { get; private set; }

/// <summary>
/// A client for GitHub's Enterprise Search Indexing API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/search_indexing/">Enterprise Search Indexing API documentation</a> for more information.
///</remarks>
/// </remarks>
public IObservableEnterpriseSearchIndexingClient SearchIndexing { get; private set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Reactive.Threading.Tasks;

namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's Enterprise Management Console API
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/enterprise/management_console/">Enterprise Management Console API documentation</a> for more information.
/// </remarks>
public class ObservableEnterpriseManagementConsoleClient : IObservableEnterpriseManagementConsoleClient
{
readonly IEnterpriseManagementConsoleClient _client;

public ObservableEnterpriseManagementConsoleClient(IGitHubClient client)
{
Ensure.ArgumentNotNull(client, "client");

_client = client.Enterprise.ManagementConsole;
}

/// <summary>
/// Gets GitHub Enterprise Maintenance Mode Status
/// </summary>
/// <remarks>
/// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status
/// </remarks>
/// <returns>The <see cref="MaintenanceModeResponse"/>.</returns>
public IObservable<MaintenanceModeResponse> GetMaintenanceMode(string managementConsolePassword)
{
Ensure.ArgumentNotNullOrEmptyString(managementConsolePassword, "managementConsolePassword");

return _client.GetMaintenanceMode(managementConsolePassword).ToObservable();
}

/// <summary>
/// Sets GitHub Enterprise Maintenance Mode
/// </summary>
/// <remarks>
/// https://developer.github.com/v3/enterprise/management_console/#check-maintenance-status
/// </remarks>
/// <returns>The <see cref="MaintenanceModeResponse"/>.</returns>
public IObservable<MaintenanceModeResponse> EditMaintenanceMode(UpdateMaintenanceRequest maintenance, string managementConsolePassword)
{
Ensure.ArgumentNotNull(maintenance, "maintenance");
Ensure.ArgumentNotNullOrEmptyString(managementConsolePassword, "managementConsolePassword");

return _client.EditMaintenanceMode(maintenance, managementConsolePassword).ToObservable();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System;
using System.Threading.Tasks;
using Octokit;
using Octokit.Tests.Integration;
using Octokit.Tests.Integration.Helpers;
using Xunit;

public class EnterpriseManagementConsoleClientTests
{
readonly IGitHubClient _github;

public EnterpriseManagementConsoleClientTests()
{
_github = EnterpriseHelper.GetAuthenticatedClient();
}

[GitHubEnterpriseManagementConsoleTest]
public async Task CanGetMaintenanceMode()
{
var maintenance = await _github.Enterprise.ManagementConsole.GetMaintenanceMode(EnterpriseHelper.ManagementConsolePassword);

Assert.NotNull(maintenance);
}

[GitHubEnterpriseManagementConsoleTest]
public async Task CanSetMaintenanceModeOff()
{
using (_github.CreateMaintenanceModeContext(true))
{
// Set maintenance mode OFF now
var maintenance = await
_github.Enterprise.ManagementConsole.EditMaintenanceMode(
new UpdateMaintenanceRequest(),
EnterpriseHelper.ManagementConsolePassword);

Assert.Equal(maintenance.Status, MaintenanceModeStatus.Off);
}
}

[GitHubEnterpriseManagementConsoleTest]
public async Task CanSetMaintenanceModeOnNow()
{
using (_github.CreateMaintenanceModeContext(false))
{
// Set maintenance mode ON now
var maintenance = await
_github.Enterprise.ManagementConsole.EditMaintenanceMode(
new UpdateMaintenanceRequest(
new UpdateMaintenanceRequestDetails(true)),
EnterpriseHelper.ManagementConsolePassword);

Assert.Equal(maintenance.Status, MaintenanceModeStatus.On);
}
}

[GitHubEnterpriseManagementConsoleTest]
public async Task CanScheduleMaintenanceModeOnWithDateTime()
{
using (_github.CreateMaintenanceModeContext(false))
{
// Schedule maintenance mode ON in 5 minutes
var scheduledTime = DateTimeOffset.Now.AddMinutes(5);
var maintenance = await
_github.Enterprise.ManagementConsole.EditMaintenanceMode(
new UpdateMaintenanceRequest(
new UpdateMaintenanceRequestDetails(true, scheduledTime)),
EnterpriseHelper.ManagementConsolePassword);

Assert.Equal(maintenance.Status, MaintenanceModeStatus.Scheduled);
}
}

[GitHubEnterpriseManagementConsoleTest]
public async Task CanScheduleMaintenanceModeOnWithPhrase()
{
using (_github.CreateMaintenanceModeContext(false))
{
// Schedule maintenance mode ON with phrase
var maintenance = await
_github.Enterprise.ManagementConsole.EditMaintenanceMode(
new UpdateMaintenanceRequest(
new UpdateMaintenanceRequestDetails(true, "tomorrow at 5pm")),
EnterpriseHelper.ManagementConsolePassword);

Assert.Equal(maintenance.Status, MaintenanceModeStatus.Scheduled);
}
}
}
20 changes: 16 additions & 4 deletions Octokit.Tests.Integration/EnterpriseHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static class EnterpriseHelper
static EnterpriseHelper()
{
// Force reading of environment variables.
// This wasn't happening if UserName/Organization were
// This wasn't happening if UserName/Organization were
// retrieved before Credentials.
Debug.WriteIf(Credentials == null, "No credentials specified.");
}
Expand Down Expand Up @@ -108,10 +108,9 @@ public static string ClientSecret
get { return Environment.GetEnvironmentVariable("OCTOKIT_GHE_CLIENTSECRET"); }
}

public static void DeleteUser(IConnection connection, User user)
public static string ManagementConsolePassword
{
if (user != null)
DeleteUser(connection, user.Login);
get { return Environment.GetEnvironmentVariable("OCTOKIT_GHE_CONSOLEPASSWORD"); }
}

public static void DeleteUser(IConnection connection, string username)
Expand Down Expand Up @@ -162,6 +161,19 @@ public static void DeletePreReceiveEnvironment(IConnection connection, PreReceiv
}
}

public static void SetMaintenanceMode(IConnection connection, bool enabled)
{
try
{
var client = new GitHubClient(connection);
client.Enterprise.ManagementConsole.EditMaintenanceMode(
new UpdateMaintenanceRequest(new UpdateMaintenanceRequestDetails(enabled)),
EnterpriseHelper.ManagementConsolePassword)
.Wait(TimeSpan.FromSeconds(15));
}
catch { }
}

public static IGitHubClient GetAuthenticatedClient()
{
return new GitHubClient(new ProductHeaderValue("OctokitEnterpriseTests"), GitHubEnterpriseUrl)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

namespace Octokit.Tests.Integration
{
public class GitHubEnterpriseManagementConsoleTestDiscoverer : IXunitTestCaseDiscoverer
{
readonly IMessageSink diagnosticMessageSink;

public GitHubEnterpriseManagementConsoleTestDiscoverer(IMessageSink diagnosticMessageSink)
{
this.diagnosticMessageSink = diagnosticMessageSink;
}

public IEnumerable<IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
{
if (Helper.Credentials == null)
return Enumerable.Empty<IXunitTestCase>();

if (!EnterpriseHelper.IsGitHubEnterpriseEnabled)
return Enumerable.Empty<IXunitTestCase>();

if (String.IsNullOrEmpty(EnterpriseHelper.ManagementConsolePassword))
return Enumerable.Empty<IXunitTestCase>();

return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) };
}
}

[XunitTestCaseDiscoverer("Octokit.Tests.Integration.GitHubEnterpriseManagementConsoleTestDiscoverer", "Octokit.Tests.Integration")]
public class GitHubEnterpriseManagementConsoleTestAttribute : FactAttribute
{
}
}
5 changes: 5 additions & 0 deletions Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,10 @@ internal static async Task<GpgKeyContext> CreateGpgKeyContext(this IGitHubClient

return new GpgKeyContext(client.Connection, key);
}

internal static MaintenanceModeContext CreateMaintenanceModeContext(this IGitHubClient client, bool enabled)
{
return new MaintenanceModeContext(client.Connection, enabled);
}
}
}
Loading

0 comments on commit 8cd0b34

Please sign in to comment.