コード例 #1
0
        /// <summary>
        /// Executes PackageSmartSignal task.
        /// </summary>
        /// <returns>True if the task successfully executed; otherwise, False.</returns>
        public override bool Execute()
        {
            try
            {
                SmartSignalPackage package = SmartSignalPackage.CreateFromFolder(this.PackagePath);
                package.SaveToFile(Path.Combine(this.PackagePath, this.PackageName));
            }
            catch (InvalidSmartSignalPackageException exception)
            {
                Log.LogError(exception.Message);
                return(false);
            }
            catch (IOException ioe)
            {
                Log.LogError($"Failed to create Smart Signal Package - failed creating the package file: {ioe.Message}");
                return(false);
            }
            catch (SecurityException securityException)
            {
                Log.LogError($"Failed to create Smart Signal Package - failed creating the package file: {securityException.Message}");
                return(false);
            }

            return(true);
        }
コード例 #2
0
        private async Task TestLoadSignalSimple(Type signalType, string expectedTitle = "test test test")
        {
            ISmartSignalLoader  loader   = new SmartSignalLoader(this.tracerMock.Object);
            SmartSignalManifest manifest = new SmartSignalManifest("3", "simple", "description", Version.Parse("1.0"), signalType.Assembly.GetName().Name, signalType.FullName, new List <ResourceType>()
            {
                ResourceType.Subscription
            }, new List <int> {
                60
            });
            SmartSignalPackage package = new SmartSignalPackage(manifest, this.assemblies["3"]);
            ISmartSignal       signal  = loader.LoadSignal(package);

            Assert.IsNotNull(signal, "Signal is NULL");

            var resource        = new ResourceIdentifier(ResourceType.VirtualMachine, "someSubscription", "someGroup", "someVM");
            var analysisRequest = new AnalysisRequest(
                new List <ResourceIdentifier> {
                resource
            },
                DateTime.UtcNow.AddDays(-1),
                TimeSpan.FromDays(1),
                new Mock <IAnalysisServicesFactory>().Object);
            SmartSignalResult signalResult = await signal.AnalyzeResourcesAsync(analysisRequest, this.tracerMock.Object, default(CancellationToken));

            Assert.AreEqual(1, signalResult.ResultItems.Count, "Incorrect number of result items returned");
            Assert.AreEqual(expectedTitle, signalResult.ResultItems.Single().Title, "Result item title is wrong");
            Assert.AreEqual(resource, signalResult.ResultItems.Single().ResourceIdentifier, "Result item resource identifier is wrong");
        }
コード例 #3
0
        /// <summary>
        /// Loads a Smart Signal.
        /// This method load the signal's assembly into the current application domain,
        /// and creates the signal object using reflection.
        /// </summary>
        /// <param name="signalPackage">The signal package.</param>
        /// <returns>The Smart Signal object.</returns>
        /// <exception cref="SmartSignalLoadException">
        /// Thrown if an error occurred during the signal load (either due to assembly load
        /// error or failure to create the signal object).
        /// </exception>
        public ISmartSignal LoadSignal(SmartSignalPackage signalPackage)
        {
            SmartSignalManifest signalManifest = signalPackage.Manifest;
            IReadOnlyDictionary <string, byte[]> signalAssemblies = signalPackage.Content;

            try
            {
                this.tracer.TraceInformation($"Read {signalAssemblies.Count} assemblies for signal ID {signalManifest.Id}");

                // Add assembly resolver, that uses the signal's assemblies
                AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
                {
                    this.tracer.TraceInformation($"Resolving assembly {args.Name} for signal ID {signalManifest.Id}");

                    // Get the short name of the assembly (AssemblyName.Name)
                    AssemblyName assemblyName = new AssemblyName(args.Name);
                    string       name         = assemblyName.Name;

                    // Try to find the assembly bytes in the signal's assemblies
                    if (signalAssemblies.TryGetValue(name, out byte[] assemblyBytes))
                    {
                        // Load the assembly from its bytes
                        return(Assembly.Load(assemblyBytes));
                    }

                    return(null);
                };

                // Find the main signal assembly
                if (!signalAssemblies.TryGetValue(signalManifest.AssemblyName, out byte[] signalMainAssemblyBytes))
コード例 #4
0
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Application.Startup" /> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the event data.</param>
        protected override void OnStartup(StartupEventArgs e)
        {
            ITracer stringTracer  = new StringTracer(string.Empty);
            ITracer consoleTracer = new ConsoleTracer(string.Empty);
            var     signalLoader  = new SmartSignalLoader(consoleTracer);

            // *Temporary*: if package file path wasn't accepted, raise file selection window to allow package file selection.
            // This option should be removed before launching version for customers (bug for tracking: 1177247)
            string signalPackagePath = e.Args.Length != 1 ?
                                       this.GetSignalPackagePath() :
                                       Diagnostics.EnsureStringNotNullOrWhiteSpace(() => e.Args[0]);

            SmartSignalPackage signalPackage;

            using (var fileStream = new FileStream(signalPackagePath, FileMode.Open))
            {
                signalPackage = SmartSignalPackage.CreateFromStream(fileStream, consoleTracer);
            }

            SmartSignalManifest signalManifest = signalPackage.Manifest;
            ISmartSignal        signal         = signalLoader.LoadSignal(signalPackage);

            // Authenticate the user to Active Directory
            var authenticationServices = new AuthenticationServices();

            authenticationServices.AuthenticateUser();
            ICredentialsFactory credentialsFactory = new ActiveDirectoryCredentialsFactory(authenticationServices);

            IAzureResourceManagerClient azureResourceManagerClient = new AzureResourceManagerClient(credentialsFactory, consoleTracer);

            // Create analysis service factory
            var queryRunInroProvider = new QueryRunInfoProvider(azureResourceManagerClient);
            var httpClientWrapper    = new HttpClientWrapper();
            IAnalysisServicesFactory analysisServicesFactory = new AnalysisServicesFactory(consoleTracer, httpClientWrapper, credentialsFactory, azureResourceManagerClient, queryRunInroProvider);

            var signalRunner = new SmartSignalRunner(signal, analysisServicesFactory, queryRunInroProvider, signalManifest, stringTracer);

            // Create a Unity container with all the required models and view models registrations
            Container = new UnityContainer();
            Container
            .RegisterInstance(stringTracer)
            .RegisterInstance(new SignalsResultsRepository())
            .RegisterInstance(authenticationServices)
            .RegisterInstance(azureResourceManagerClient)
            .RegisterInstance(signal)
            .RegisterInstance(signalManifest)
            .RegisterInstance(analysisServicesFactory)
            .RegisterInstance(signalRunner);
        }
コード例 #5
0
        /// <summary>
        /// Reads a smart signal's package from the repository
        /// </summary>
        /// <param name="signalId">The signal's ID</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A <see cref="Task{TResult}"/> returning the signal package</returns>
        public async Task <SmartSignalPackage> ReadSignalPackageAsync(string signalId, CancellationToken cancellationToken)
        {
            this.tracer.TraceInformation($"Getting smart signal {signalId} package");
            try
            {
                CloudBlob latestVersionSignalBlob = await this.GetLatestSignalBlobVersionAsync(signalId, cancellationToken);

                this.tracer.TraceInformation($"Last version signal BLOB is {latestVersionSignalBlob.Name}");

                using (var blobMemoryStream = new MemoryStream())
                {
                    // Download the blob to a stream and generate the signal package from it
                    await latestVersionSignalBlob.DownloadToStreamAsync(blobMemoryStream, cancellationToken);

                    return(SmartSignalPackage.CreateFromStream(blobMemoryStream, this.tracer));
                }
            }
            catch (StorageException e)
            {
                throw new SmartSignalRepositoryException("Failed to get signal package from storage", e);
            }
        }
コード例 #6
0
        private async Task TestLoadSignalFromDll(string signalId, string expectedTitle)
        {
            ISmartSignalLoader loader  = new SmartSignalLoader(this.tracerMock.Object);
            SmartSignalPackage package = new SmartSignalPackage(this.manifests[signalId], this.assemblies[signalId]);
            ISmartSignal       signal  = loader.LoadSignal(package);

            Assert.IsNotNull(signal, "Signal is NULL");

            var resource        = new ResourceIdentifier(ResourceType.VirtualMachine, "someSubscription", "someGroup", "someVM");
            var analysisRequest = new AnalysisRequest(
                new List <ResourceIdentifier> {
                resource
            },
                DateTime.UtcNow.AddDays(-1),
                TimeSpan.FromDays(1),
                new Mock <IAnalysisServicesFactory>().Object);
            SmartSignalResult signalResult = await signal.AnalyzeResourcesAsync(analysisRequest, this.tracerMock.Object, default(CancellationToken));

            Assert.AreEqual(1, signalResult.ResultItems.Count, "Incorrect number of result items returned");
            Assert.AreEqual(expectedTitle, signalResult.ResultItems.Single().Title, "Result item title is wrong");
            Assert.AreEqual(resource, signalResult.ResultItems.Single().ResourceIdentifier, "Result item resource identifier is wrong");
        }
コード例 #7
0
        /// <summary>
        /// Loads the signal, runs it, and returns the generated result presentations
        /// </summary>
        /// <param name="request">The signal request</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>A <see cref="Task{TResult}"/>, returning the list of Smart Signal result item presentations generated by the signal</returns>
        public async Task <List <SmartSignalResultItemPresentation> > RunAsync(SmartSignalRequest request, CancellationToken cancellationToken)
        {
            // Read the signal's package
            this.tracer.TraceInformation($"Loading signal package for signal ID {request.SignalId}");
            SmartSignalPackage signalPackage = await this.smartSignalRepository.ReadSignalPackageAsync(request.SignalId, cancellationToken);

            SmartSignalManifest signalManifest = signalPackage.Manifest;

            this.tracer.TraceInformation($"Read signal package, ID {signalManifest.Id}, Version {signalManifest.Version}");

            // Load the signal
            ISmartSignal signal = this.smartSignalLoader.LoadSignal(signalPackage);

            this.tracer.TraceInformation($"Signal instance loaded successfully, ID {signalManifest.Id}");

            // Get the resources on which to run the signal
            List <ResourceIdentifier> resources = await this.GetResourcesForSignal(request.ResourceIds, signalManifest, cancellationToken);

            // Run the signal
            this.tracer.TraceInformation($"Started running signal ID {signalManifest.Id}, Name {signalManifest.Name}");
            SmartSignalResult signalResult;

            try
            {
                var analysisRequest = new AnalysisRequest(resources, request.LastExecutionTime, request.Cadence, this.analysisServicesFactory);
                signalResult = await signal.AnalyzeResourcesAsync(analysisRequest, this.tracer, cancellationToken);

                this.tracer.TraceInformation($"Completed running signal ID {signalManifest.Id}, Name {signalManifest.Name}, returning {signalResult.ResultItems.Count} result items");
            }
            catch (Exception e)
            {
                this.tracer.TraceInformation($"Failed running signal ID {signalManifest.Id}, Name {signalManifest.Name}: {e.Message}");
                throw new SmartSignalCustomException(e.GetType().ToString(), e.Message, e.StackTrace);
            }

            // Verify that each result item belongs to one of the types declared in the signal manifest
            foreach (SmartSignalResultItem resultItem in signalResult.ResultItems)
            {
                if (!signalManifest.SupportedResourceTypes.Contains(resultItem.ResourceIdentifier.ResourceType))
                {
                    throw new UnidentifiedResultItemResourceTypeException(resultItem.ResourceIdentifier);
                }
            }

            // Trace the number of result items of each type
            foreach (var resultItemType in signalResult.ResultItems.GroupBy(x => x.GetType().Name))
            {
                this.tracer.TraceInformation($"Got {resultItemType.Count()} Smart Signal result items of type '{resultItemType.Key}'");
                this.tracer.ReportMetric("SignalResultItemType", resultItemType.Count(), new Dictionary <string, string>()
                {
                    { "ResultItemType", resultItemType.Key }
                });
            }

            // Create results
            List <SmartSignalResultItemPresentation> results = new List <SmartSignalResultItemPresentation>();

            foreach (var resultItem in signalResult.ResultItems)
            {
                SmartSignalResultItemQueryRunInfo queryRunInfo = await this.queryRunInfoProvider.GetQueryRunInfoAsync(new List <ResourceIdentifier>() { resultItem.ResourceIdentifier }, cancellationToken);

                results.Add(SmartSignalResultItemPresentation.CreateFromResultItem(request, signalManifest.Name, resultItem, queryRunInfo));
            }

            this.tracer.TraceInformation($"Returning {results.Count} results");
            return(results);
        }
コード例 #8
0
        private void TestInitialize(ResourceType requestResourceType, ResourceType signalResourceType)
        {
            this.tracerMock = new Mock <ITracer>();

            ResourceIdentifier resourceId;

            switch (requestResourceType)
            {
            case ResourceType.Subscription:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", string.Empty, string.Empty);
                break;

            case ResourceType.ResourceGroup:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", "resourceGroup", string.Empty);
                break;

            default:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", "resourceGroup", "resourceName");
                break;
            }

            this.resourceIds = new List <string>()
            {
                resourceId.ToResourceId()
            };
            this.request = new SmartSignalRequest(this.resourceIds, "1", DateTime.UtcNow.AddDays(-1), TimeSpan.FromDays(1), new SmartSignalSettings());

            var smartSignalManifest = new SmartSignalManifest("1", "Test signal", "Test signal description", Version.Parse("1.0"), "assembly", "class", new List <ResourceType>()
            {
                signalResourceType
            }, new List <int> {
                60
            });

            this.smartSignalPackage = new SmartSignalPackage(smartSignalManifest, new Dictionary <string, byte[]> {
                ["TestSignalLibrary"] = new byte[0]
            });

            this.smartSignalsRepositoryMock = new Mock <ISmartSignalRepository>();
            this.smartSignalsRepositoryMock
            .Setup(x => x.ReadSignalPackageAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => this.smartSignalPackage);

            this.analysisServicesFactoryMock = new Mock <IAnalysisServicesFactory>();

            this.signal = new TestSignal {
                ExpectedResourceType = signalResourceType
            };

            this.smartSignalLoaderMock = new Mock <ISmartSignalLoader>();
            this.smartSignalLoaderMock
            .Setup(x => x.LoadSignal(this.smartSignalPackage))
            .Returns(this.signal);

            this.azureResourceManagerClientMock = new Mock <IAzureResourceManagerClient>();
            this.azureResourceManagerClientMock
            .Setup(x => x.GetAllResourceGroupsInSubscriptionAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.ResourceGroup, subscriptionId, "resourceGroupName", string.Empty)
            });
            this.azureResourceManagerClientMock
            .Setup(x => x.GetAllResourcesInSubscriptionAsync(It.IsAny <string>(), It.IsAny <IEnumerable <ResourceType> >(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, IEnumerable <ResourceType> resourceTypes, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.VirtualMachine, subscriptionId, "resourceGroupName", "resourceName")
            });
            this.azureResourceManagerClientMock
            .Setup(x => x.GetAllResourcesInResourceGroupAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IEnumerable <ResourceType> >(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, string resourceGroupName, IEnumerable <ResourceType> resourceTypes, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.VirtualMachine, subscriptionId, resourceGroupName, "resourceName")
            });

            this.queryRunInfoProviderMock = new Mock <IQueryRunInfoProvider>();
        }