Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.PowerBI.Common.Abstractions;
using Microsoft.PowerBI.Common.Abstractions.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.PowerBI.Commands.Common.Test
{
public class TestPowerBICmdletNoClientInitFactory : PowerBICmdletInitFactory
{
public IPowerBIProfile Profile { get; set; }

public TestLogger Logger
{
get
{
if (this.LoggerFactory is TestLoggerFactory logger)
{
return logger.Logger;
}

return null;
}
}

/// <summary>
/// Constructor for TestPowerBICmdletNoClientInitFactory.
/// Used by tests\cmdlets that don't need a client.
/// </summary>
/// <param name="setProfile">True if profile should be assigned; false otherwise. If testing cmdlets for profile assignment, pass false.</param>
/// <param name="profile">Profile to assign, only assigned if setProfile is true. If setProfile is true and profile is null, TestProfile will be constructed for assignment.</param>
public TestPowerBICmdletNoClientInitFactory(bool setProfile, IPowerBIProfile profile = null) :
base(new TestLoggerFactory(), new ModuleDataStorage(), new TestAuthenticator(), new PowerBISettings())
{
if(setProfile)
{
this.SetProfile(profile);
}
}

public void SetProfile(IPowerBIProfile profile = null)
{
if (profile == null)
{
this.Profile = new TestProfile();
}
else if (this.Profile != profile)
{
this.Profile = profile;
}

this.Storage.SetItem("profile", this.Profile);
}

public IPowerBIProfile GetProfileFromStorage()
{
if (this.Storage.TryGetItem("profile", out IPowerBIProfile profile)) {
return profile;
}

return null;
}

public void AssertExpectedUnitTestResults<T>(IEnumerable<T> expected)
{
Assert.IsFalse(this.Logger.ErrorRecords.Any());
var results = this.Logger.Output.ToList();
Assert.AreEqual(expected.Count(), results.Count());
var castedResults = results.Cast<T>().ToList();
CollectionAssert.AreEqual(expected.ToList(), castedResults);
}
}
}
17 changes: 12 additions & 5 deletions src/Common/Commands.Common/PowerBISettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public class PowerBISettings : IPowerBISettings
{
private IConfigurationRoot Configuration { get; }

private static GSEnvironments GlobalServiceEnvironments { get; set; }

public PowerBISettings(IConfigurationBuilder builder = null)
{
var executingDirectory = this.GetExecutingDirectory();
Expand Down Expand Up @@ -83,14 +85,19 @@ public PowerBISettings(IConfigurationBuilder builder = null)

public async Task<GSEnvironments> GetGlobalServiceConfig(string clientName = "powerbi-msolap")
{
using (var client = new HttpClient())
if(GlobalServiceEnvironments == null)
{
client.DefaultRequestHeaders.Accept.Clear();
var response = await client.PostAsync("https://api.powerbi.com/powerbi/globalservice/v201606/environments/discover?client=" + clientName, null);
var serializer = new DataContractJsonSerializer(typeof(GSEnvironments));
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
var response = await client.PostAsync("https://api.powerbi.com/powerbi/globalservice/v201606/environments/discover?client=" + clientName, null);
var serializer = new DataContractJsonSerializer(typeof(GSEnvironments));

return serializer.ReadObject(await response.Content.ReadAsStreamAsync()) as GSEnvironments;
GlobalServiceEnvironments = serializer.ReadObject(await response.Content.ReadAsStreamAsync()) as GSEnvironments;
}
}

return GlobalServiceEnvironments;
}

public IDictionary<PowerBIEnvironmentType, IPowerBIEnvironment> Environments { get; }
Expand Down
27 changes: 27 additions & 0 deletions src/Modules/Data/Commands.Data.Test/GetPowerBIDatasetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
* Licensed under the MIT License.
*/

using System;
using System.Collections.Generic;
using System.Management.Automation;
using Microsoft.PowerBI.Commands.Common.Test;
using Microsoft.PowerBI.Commands.Profile.Test;
using Microsoft.PowerBI.Common.Abstractions;
using Microsoft.PowerBI.Common.Api;
using Microsoft.PowerBI.Common.Api.Datasets;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Microsoft.PowerBI.Commands.Data
{
Expand Down Expand Up @@ -35,5 +41,26 @@ public void EndToEndGetPowerBIDatasetOrganizationScope()
Assert.IsTrue(result.Count > 0);
}
}

[TestMethod]
public void GetPowerBIDatasetIndividualScope_ListParameterSet()
{
// Arrange
var expectedDatasets = new List<Dataset> { new Dataset { Id = Guid.NewGuid(), Name = "TestDataset" } };
var client = new Mock<IPowerBIApiClient>();
client.Setup(x => x.Datasets.GetDatasets()).Returns(expectedDatasets);
var initFactory = new TestPowerBICmdletInitFactory(client.Object);
var cmdlet = new GetPowerBIDataset(initFactory)
{
Scope = PowerBIUserScope.Individual,
ParameterSet = "List",
};

// Act
cmdlet.InvokePowerBICmdlet();

// Assert
initFactory.AssertExpectedUnitTestResults(expectedDatasets);
}
}
}
72 changes: 71 additions & 1 deletion src/Modules/Data/Commands.Data.Test/GetPowerBIDatasourceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,27 @@ public class GetPowerBIDatasourceTests
[TestCategory("SkipWhenLiveUnitTesting")] // Ignore for Live Unit Testing
public void EndToEndGetPowerBIDatasourceIndividualScope()
{
/*
* Requirement to run test:
* Need at least one dataset containing a datasource assigned to the user logging into the test.
*/

using (var ps = System.Management.Automation.PowerShell.Create())
{
// Arrange
ProfileTestUtilities.ConnectToPowerBI(ps);
ps.AddCommand(GetPowerBIDatasourceCmdletInfo).AddParameter(nameof(GetPowerBIDatasource.DatasetId), "b077389f-0238-4312-b014-0c6212fc904e");
ps.AddCommand(GetPowerBIDatasetTests.GetPowerBIDatasetCmdletInfo);
var existingDatasets = ps.Invoke();
TestUtilities.AssertNoCmdletErrors(ps);
ps.Commands.Clear();

if(!existingDatasets.Any())
{
Assert.Inconclusive("No datasets returned. Verify you have datasets under your logged in user.");
}

var testDataset = existingDatasets.Select(d => (Dataset)d.BaseObject).FirstOrDefault();
ps.AddCommand(GetPowerBIDatasourceCmdletInfo).AddParameter(nameof(GetPowerBIDatasource.DatasetId), testDataset.Id.ToString());

// Act
var result = ps.Invoke();
Expand Down Expand Up @@ -91,6 +107,37 @@ public void EndToEndGetPowerBIDatasourceOrganizationScopeAndWorkspaceId()
}
}

[TestMethod]
[TestCategory("Interactive")]
[TestCategory("SkipWhenLiveUnitTesting")] // Ignore for Live Unit Testing
public void EndToEndPipingDatasetIntoGetPowerBIDatasourceIndividualScope()
{
/*
* Requirement to run test:
* Need at least one dataset containing a datasource assigned to the user logging into the test.
*/

using (var ps = System.Management.Automation.PowerShell.Create())
{
// Arrange
ProfileTestUtilities.ConnectToPowerBI(ps, nameof(PowerBIEnvironmentType.Public));
ps.AddCommand(GetPowerBIDatasetTests.GetPowerBIDatasetCmdletInfo).AddCommand(GetPowerBIDatasourceCmdletInfo);

// Act
var results = ps.Invoke();

// Assert
TestUtilities.AssertNoCmdletErrors(ps);
Assert.IsNotNull(results);
if (!results.Any())
{
Assert.Inconclusive("No datasources returned. Verify you have datasources under your logged in user.");
}

Assert.IsTrue(results.Count > 0);
}
}

[TestMethod]
public void GetPowerBIDatasourceIndividualScope_ListParameterSet()
{
Expand Down Expand Up @@ -161,5 +208,28 @@ public void GetPowerBIDatasourceOrganizationScope_ListParameterSet()
// Assert
initFactory.AssertExpectedUnitTestResults(expectedDatasources);
}

[TestMethod]
public void GetPowerBIDatasourceIndividualScope_ObjectAndListParameterSet()
{
// Arrange
var testDataset = new Dataset { Id = Guid.NewGuid(), Name = "TestDataset" };
var expectedDatasources = new List<Datasource> { new Datasource { DatasourceId = Guid.NewGuid().ToString(), Name = "TestDatasource", GatewayId = Guid.NewGuid().ToString() } };
var client = new Mock<IPowerBIApiClient>();
client.Setup(x => x.Datasets.GetDatasources(testDataset.Id, null)).Returns(expectedDatasources);
var initFactory = new TestPowerBICmdletInitFactory(client.Object);
var cmdlet = new GetPowerBIDatasource(initFactory)
{
Scope = PowerBIUserScope.Individual,
Dataset = testDataset,
ParameterSet = "ObjectAndList",
};

// Act
cmdlet.InvokePowerBICmdlet();

// Assert
initFactory.AssertExpectedUnitTestResults(expectedDatasources);
}
}
}
2 changes: 2 additions & 0 deletions src/Modules/Data/Commands.Data/GetPowerBIDatasource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ public class GetPowerBIDatasource : PowerBIClientCmdlet, IUserScope

[Alias("DatasourceId")]
[Parameter(Mandatory = true, ParameterSetName = IdParameterSetName)]
[Parameter(Mandatory = true, ParameterSetName = ObjectIdParameterSetName)]
public Guid Id { get; set; }

[Alias("DatasoureName")]
[Parameter(Mandatory = true, ParameterSetName = NameParameterSetName)]
[Parameter(Mandatory = true, ParameterSetName = ObjectNameParameterSetName)]
public string Name { get; set; }

[Parameter(Mandatory = false)]
Expand Down
3 changes: 2 additions & 1 deletion src/Modules/Data/Commands.Data/help/Get-PowerBIDataset.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Get-PowerBIDataset [-Scope <PowerBIUserScope>] [-First <Int32>] [-Skip <Int32>]
## DESCRIPTION
Retrieves a list of Power BI datasets that match the specified search criteria and scope.
Before you run this command, make sure you log in using Connect-PowerBIServiceAccount.
For -Scope Individual, datasets are returned from "My Workspace" unless -Workspace or -WorkspaceId is specified.

## EXAMPLES

Expand Down Expand Up @@ -127,7 +128,7 @@ Accept wildcard characters: False
```

### -Scope
Indicates scope of the call. Individual returns only datasets assigned to the caller; Organization returns all datasets within a tenant (must be an administrator to initiate). Individual is the default.
Indicates scope of the call. Individual returns datasets from "My Workspace" by default. With -Workspace or -WorkspaceId, datasets under the workspace assigned to the caller are returned; Organization returns all datasets within a tenant (must be an administrator to initiate). Individual is the default.

```yaml
Type: PowerBIUserScope
Expand Down
10 changes: 6 additions & 4 deletions src/Modules/Data/Commands.Data/help/Get-PowerBIDatasource.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ Get-PowerBIDatasource -DatasetId <Guid> [-WorkspaceId <Guid>] -Name <String> [-S

### ObjectAndId
```
Get-PowerBIDatasource -Dataset <Dataset> [-WorkspaceId <Guid>] [-Scope <PowerBIUserScope>] [<CommonParameters>]
Get-PowerBIDatasource -Dataset <Dataset> [-WorkspaceId <Guid>] -Id <Guid> [-Scope <PowerBIUserScope>]
[<CommonParameters>]
```

### ObjectAndName
```
Get-PowerBIDatasource -Dataset <Dataset> [-WorkspaceId <Guid>] [-Scope <PowerBIUserScope>] [<CommonParameters>]
Get-PowerBIDatasource -Dataset <Dataset> [-WorkspaceId <Guid>] -Name <String> [-Scope <PowerBIUserScope>]
[<CommonParameters>]
```

### ObjectAndList
Expand Down Expand Up @@ -101,7 +103,7 @@ Id of the data source to return.

```yaml
Type: Guid
Parameter Sets: Id
Parameter Sets: Id, ObjectAndId
Aliases: DatasourceId

Required: True
Expand All @@ -116,7 +118,7 @@ Name of the data source to return if one exists with that name. Case insensitive

```yaml
Type: String
Parameter Sets: Name
Parameter Sets: Name, ObjectAndName
Aliases: DatasoureName

Required: True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
* Licensed under the MIT License.
*/

using System.Management.Automation;
using System.Security;
using Microsoft.PowerBI.Commands.Common.Test;
using Microsoft.PowerBI.Common.Abstractions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics.CodeAnalysis;
using Microsoft.PowerBI.Commands.Common.Test;

namespace Microsoft.PowerBI.Commands.Profile.Test
{
Expand Down Expand Up @@ -48,5 +49,29 @@ public void EndToEndInteractiveLogin()
Assert.AreEqual(0, results.Count);
}
}

[TestMethod]
public void ConnectPowerBIServiceAccountServiceWithTenantId_PrincipalParameterSet()
{
// Arrange
var initFactory = new TestPowerBICmdletNoClientInitFactory(false);
var testTenantName = "test.microsoftonline.com";
var cmdlet = new ConnectPowerBIServiceAccount(initFactory)
{
Tenant = testTenantName,
ServicePrincipal = true,
Credential = new PSCredential("appId", new SecureString()),
ParameterSet = "ServicePrincipal"
};

// Act
cmdlet.InvokePowerBICmdlet();

// Assert
var profile = initFactory.GetProfileFromStorage();
Assert.IsNotNull(profile);
Assert.IsTrue(profile.Environment.AzureADAuthority.Contains(testTenantName));
initFactory.AssertExpectedUnitTestResults(new[] { profile });
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public class ConnectPowerBIServiceAccount : PowerBICmdlet
[Parameter(Mandatory = false)]
public PowerBIEnvironmentType Environment { get; set; } = PowerBIEnvironmentType.Public;

[Parameter(ParameterSetName = UserParameterSet, Mandatory = false)]
[Parameter(ParameterSetName = ServicePrincipalParameterSet, Mandatory = true)]
public PSCredential Credential { get; set; }

Expand All @@ -45,6 +44,11 @@ public class ConnectPowerBIServiceAccount : PowerBICmdlet
[Parameter(ParameterSetName = ServicePrincipalParameterSet, Mandatory = true)]
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet, Mandatory = true)]
public SwitchParameter ServicePrincipal { get; set; }

[Alias("TenantId")]
[Parameter(ParameterSetName = ServicePrincipalParameterSet, Mandatory = false)]
[Parameter(ParameterSetName = ServicePrincipalCertificateParameterSet, Mandatory = false)]
public string Tenant { get; set; }
#endregion

#region Constructors
Expand All @@ -56,6 +60,13 @@ public ConnectPowerBIServiceAccount(IPowerBICmdletInitFactory init) : base(init)
public override void ExecuteCmdlet()
{
var environment = this.Settings.Environments[this.Environment];
if(!string.IsNullOrEmpty(this.Tenant))
{
var tempEnvironment = (PowerBIEnvironment) environment;
tempEnvironment.AzureADAuthority = tempEnvironment.AzureADAuthority.ToLowerInvariant().Replace("/common", $"/{this.Tenant}");
this.Logger.WriteVerbose($"Updated Azure AD authority with -Tenant specified, new value: {tempEnvironment.AzureADAuthority}");
environment = tempEnvironment;
}

this.Authenticator.Challenge(); // revoke any previous login
IAccessToken token = null;
Expand Down
Loading