Skip to content

BUG: 1933802 Create Powershell Commandlets for Event Service #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 21, 2015
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
6 changes: 6 additions & 0 deletions src/AzurePowershell.sln
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics.Test", "ResourceManager\StreamAnalytics\Commands.StreamAnalytics.Test\Commands.StreamAnalytics.Test.csproj", "{7E6683BE-ECFF-4709-89EB-1325E9E70512}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Insights", "ResourceManager\Insights\Commands.Insights\Commands.Insights.csproj", "{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -385,6 +387,10 @@ Global
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.Build.0 = Release|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
8 changes: 7 additions & 1 deletion src/ResourceManager.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30501.0
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8531411A-0137-4E27-9C5E-49E07C245048}"
ProjectSection(SolutionItems) = preProject
Expand Down Expand Up @@ -47,6 +47,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.StreamAnalytics.Test", "ResourceManager\StreamAnalytics\Commands.StreamAnalytics.Test\Commands.StreamAnalytics.Test.csproj", "{7E6683BE-ECFF-4709-89EB-1325E9E70512}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commands.Insights", "ResourceManager\Insights\Commands.Insights\Commands.Insights.csproj", "{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -125,6 +127,10 @@ Global
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E6683BE-ECFF-4709-89EB-1325E9E70512}.Release|Any CPU.Build.0 = Release|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DEA446A1-84E2-46CC-B780-EB4AFDE2460E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.Azure.Commands.Insights</RootNamespace>
<AssemblyName>Microsoft.Azure.Commands.Insights</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\Package\Debug\ResourceManager\AzureResourceManager\Insights\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>true</RunCodeAnalysis>
<Prefer32Bit>false</Prefer32Bit>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\Package\Release\ResourceManager\AzureResourceManager\Insights\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>true</DelaySign>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Hyak.Common">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Hyak.Common.1.0.1\lib\portable-net403+win+wpa81\Hyak.Common.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.Insights">
<HintPath>..\..\..\packages\Microsoft.Azure.Insights.0.6.0-preview\lib\net45\Microsoft.Azure.Insights.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.Common">
<HintPath>..\..\..\packages\Microsoft.Azure.Common.2.0.1\lib\net45\Microsoft.Azure.Common.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.Common.NetFramework">
<HintPath>..\..\..\packages\Microsoft.Azure.Common.2.0.1\lib\net45\Microsoft.Azure.Common.NetFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Azure.Common.Extensions">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Microsoft.Azure.Common.Extensions.0.13.0-preview\lib\net45\Microsoft.Azure.Common.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Compile Include="EventCmdletBase.cs" />
<Compile Include="GetAzureResourceGroupLogCommand.cs" />
<Compile Include="GetAzureResourceLogCommand.cs" />
<Compile Include="GetAzureResourceProviderLogCommand.cs" />
<Compile Include="GetAzureCorrelationIdLogCommand.cs" />
<Compile Include="GetAzureSubscriptionIdLogCommand.cs" />
<Compile Include="InsightsCmdletBase.cs" />
<Compile Include="OutputClasses\IPSEventData.cs" />
<Compile Include="OutputClasses\PSDictionaryElement.cs" />
<Compile Include="OutputClasses\PSEventData.cs" />
<Compile Include="OutputClasses\PSEventDataAuthorization.cs" />
<Compile Include="OutputClasses\PSEventDataHttpRequest.cs" />
<Compile Include="OutputClasses\PSEventDataNoDetails.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="MSSharedLibKey.snk" />
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Common\Commands.Common\Commands.Common.csproj">
<Project>{5ee72c53-1720-4309-b54b-5fb79703195f}</Project>
<Name>Commands.Common</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Microsoft.Azure.Commands.Insights.dll-Help.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<Import Project="..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\..\..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
186 changes: 186 additions & 0 deletions src/ResourceManager/Insights/Commands.Insights/EventCmdletBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using Microsoft.Azure.Commands.Insights.OutputClasses;
using Microsoft.Azure.Insights;
using Microsoft.Azure.Insights.Models;

namespace Microsoft.Azure.Commands.Insights
{
/// <summary>
/// Base class for the Azure SDK EventService Cmdlets
/// </summary>
public abstract class EventCmdletBase : InsightsCmdletBase
{
internal static readonly TimeSpan DefaultQueryTimeRange = TimeSpan.FromHours(-1);

internal static int MaxNumberOfReturnedRecords = 100000;

internal const string SubscriptionLevelName = "Query at subscription level";
internal const string ResourceProviderName = "Query on ResourceProvider";
internal const string ResourceGroupName = "Query on ResourceGroupProvider";
internal const string ResourceUriName = "Query on ResourceUriName";
internal const string CorrelationIdName = "Query on CorrelationId";

#region Optional parameters declarations

/// <summary>
/// Gets or sets the starttime parameter of the cmdlet
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The startTime of the query")]
[ValidateNotNullOrEmpty]
public string StartTime { get; set; }

/// <summary>
/// Gets or sets the endtime parameter of the cmdlet
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The endTime of the query")]
[ValidateNotNullOrEmpty]
public string EndTime { get; set; }

/// <summary>
/// Gets or sets the status parameter of the cmdlet
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The status of the records to fetch")]
[ValidateNotNullOrEmpty]
public string Status { get; set; }

/// <summary>
/// Gets or sets the caller parameter of the cmdlet
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "The caller of the records to fetch")]
[ValidateNotNullOrEmpty]
public string Caller { get; set; }

/// <summary>
/// Gets or sets the detailedoutput parameter of the cmdlet
/// </summary>
[Parameter(ValueFromPipelineByPropertyName = true, HelpMessage = "Return object with all the details of the records (the default is to return only some attributes, i.e. no detail)")]
public SwitchParameter DetailedOutput { get; set; }

#endregion

#region Parameters processing

/// <summary>
/// Adds a condition to the query filter based on the give name and the value
/// </summary>
/// <param name="currentQueryFilter">The current query filter</param>
/// <param name="name">The name to be used in the new condition</param>
/// <param name="value">The value to be used in the new condition.<para>If this value is null, the currentQueryFilter is returned unmodified.</para></param>
/// <returns></returns>
protected string AddConditionIfPResent(string currentQueryFilter, string name, string value)
{
return !string.IsNullOrWhiteSpace(value) ? string.Format("{0} and {1} eq '{2}'", currentQueryFilter, name, value) : currentQueryFilter;
}

/// <summary>
/// Process the parameters defined by this class
/// </summary>
/// <returns>The query filter with the conditions for general parameters (i.e. defined by this class) added</returns>
private string ProcessGeneralParameters()
{
DateTime startTime;
if (string.IsNullOrWhiteSpace(this.StartTime))
{
// Default to one hour from Now
startTime = DateTime.Now.Subtract(DefaultQueryTimeRange);
}
else if (!DateTime.TryParse(this.StartTime, out startTime))
{
throw new ArgumentException("Unable to parse startTime argument");
}

string queryFilter;

// EndTime is optional
if (string.IsNullOrWhiteSpace(this.EndTime))
{
queryFilter = string.Format("eventTimestamp ge '{0:o}'", startTime.ToUniversalTime());
}
else
{
DateTime endTime;
if (!DateTime.TryParse(this.EndTime, out endTime))
{
throw new ArgumentException("Unable to parse endTime argument");
}

queryFilter = string.Format("eventTimestamp ge '{0:o}' and eventTimestamp le '{1:o}'", startTime.ToUniversalTime(), endTime.ToUniversalTime());
}

// Include the status if present
queryFilter = this.AddConditionIfPResent(queryFilter, "status", this.Status);

// Include the caller if present
queryFilter = this.AddConditionIfPResent(queryFilter, "caller", this.Caller);

return queryFilter;
}

/// <summary>
/// Process the general parameters (i.e. defined in this class) and the particular parameters (i.e. the parameters added by the descendants of this class).
/// </summary>
/// <returns>The final query filter to be used by the cmdlet</returns>
protected string ProcessParameters()
{
string queryFilter = this.ProcessGeneralParameters();
return this.ProcessParticularParameters(queryFilter);
}

/// <summary>
/// Process the parameters defined by the descendants of this class
/// </summary>
/// <param name="currentQueryFilter">The current query filter</param>
/// <returns>The query filter with the conditions for particular parameters added</returns>
protected abstract string ProcessParticularParameters(string currentQueryFilter);

#endregion

/// <summary>
/// Execute the cmdlet
/// </summary>
public override void ExecuteCmdlet()
{
string queryFilter = this.ProcessParameters();

// Call the proper API methods to return a list of raw records. In the future this pattern can be extended to include DigestRecords
Func<string, string, EventDataListResponse> initialCall = (f, s) => this.InsightsClient.EventOperations.ListEvents(filterString: f, selectedProperties: s);
Func<string, EventDataListResponse> nextCall = (n) => this.InsightsClient.EventOperations.ListEventsNext(nextLink: n);

// Retrieve the records
var fullDetails = this.DetailedOutput.IsPresent;

// If fullDetails is present do not select fields, if not present fetch only the SelectedFieldsForQuery
EventDataListResponse response = initialCall.Invoke(queryFilter, fullDetails ? null : PSEventDataNoDetails.SelectedFieldsForQuery);
var records = new List<IPSEventData>(response.EventDataCollection.Value.Select(e => fullDetails ? (IPSEventData)new PSEventData(e) : (IPSEventData)new PSEventDataNoDetails(e)));
string nextLink = response.EventDataCollection.NextLink;

// Adding a safety check to stop returning records if too many have been read already.
while (!string.IsNullOrWhiteSpace(nextLink) && records.Count < MaxNumberOfReturnedRecords)
{
response = nextCall.Invoke(nextLink);
records.AddRange(response.EventDataCollection.Value.Select(e => fullDetails ? (IPSEventData)new PSEventData(e) : (IPSEventData)new PSEventDataNoDetails(e)));
nextLink = response.EventDataCollection.NextLink;
}

// Returns an object that contains a link to the set of subsequent records or null if not more records are available, called Next, and an array of records, called Value
WriteObject(sendToPipeline: records, enumerateCollection: true);
}
}
}
Loading