예제 #1
0
        public void ReadConfiguration()
        {
#if NET452
            System.Configuration.ConfigurationManager.ConnectionStrings.SetWritable().Add(new System.Configuration.ConnectionStringSettings("RabbitMQConnectionString", "ConnString"));
#endif
            int overrideCallsCount = 0;
            var settings           = new NAMESettings()
            {
                ConnectionStringProviderOverride = (node) =>
                {
                    overrideCallsCount = overrideCallsCount + 1;
                    return(null);
                }
            };

            ParsedDependencies configuration = DependenciesReader.ReadDependencies(CONFIGURATION_FILE, new DummyFilePathMapper(), settings, new NAMEContext());

#if NET452
            Assert.Equal(4, configuration.InfrastructureDependencies.Count());
            Assert.Equal(2, configuration.ServiceDependencies.Count());
            Assert.Equal(1, overrideCallsCount);
#else
            Assert.Equal(3, configuration.InfrastructureDependencies.Count());
            Assert.Equal(2, configuration.ServiceDependencies.Count());
            Assert.Equal(0, overrideCallsCount);
#endif
            var elasticsearchDependency = configuration.InfrastructureDependencies.OfType <VersionedDependency>().Single(d => d.Type == SupportedDependencies.Elasticsearch);
            var castedMaxVersion        = Assert.IsAssignableFrom <WildcardDependencyVersion>(elasticsearchDependency.MaximumVersion);
            Assert.False(castedMaxVersion.IsMajorWildcard);
            Assert.True(castedMaxVersion.IsMinorWildcard);
        }
예제 #2
0
        public bool Start(int port, NAMESettings settings)
        {
            try
            {
                this.webHost = new WebHostBuilder()
                               .UseKestrel()
                               .UseStartup <ServerStartup>()
                               .UseUrls($"http://{this.nameConfiguration.AddressToListenOn}:{port}/{this.nameConfiguration.ManifestUriPrefix.TrimStart('/').TrimEnd('/')}/")
                               .ConfigureServices((services) =>
                {
                    services.AddSingleton(settings);
                    services.AddSingleton(this.nameConfiguration);
                    services.AddSingleton(this.pathMapper);
                })
                               .Build();

                this.webHost.Start();

                this.Port = port;

                return(true);
            }
            catch (Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException)
            {
                this.webHost?.Dispose();
                return(false);
            }
        }
예제 #3
0
 public NAMEHandler(string apiName, string apiVersion, string dependenciesFile, IFilePathMapper pathMapper, NAMESettings settings)
 {
     this.apiName          = apiName;
     this.apiVersion       = apiVersion;
     this.dependenciesFile = dependenciesFile;
     this.pathMapper       = pathMapper;
     this.settings         = settings;
 }
예제 #4
0
        public void ReadConfiguration_CallsMultipleTimes_ConnectionStringProviderOverride()
        {
            string fileContents = @"{
                ""infrastructure_dependencies"": [
                ],
                ""service_dependencies"": [
                    {
                        ""name"": ""Some Service0"",
                        ""min_version"": ""0.3"",
                        ""max_version"": ""*"",
                        ""connection_string"": {
                            ""unrecognizedString"": 0
                        }
                    },
                    {
                        ""name"": ""Some Service1"",
                        ""min_version"": ""0.3"",
                        ""max_version"": ""*"",
                        ""connection_string"": {
                            ""unrecognizedString"": 1
                        }
                    }
                ]
            }";
            string fileName     = Guid.NewGuid() + ".json";

            File.WriteAllText(fileName, fileContents);
            try
            {
                int iterationsCount = 0;
                var settings        = new NAMESettings()
                {
                    ConnectionStringProviderOverride = (node) =>
                    {
                        Assert.Equal(iterationsCount, node["unrecognizedString"].AsInt);
                        iterationsCount++;
                        return(new StaticConnectionStringProvider(iterationsCount.ToString()));
                    }
                };

                ParsedDependencies configuration = DependenciesReader.ReadDependencies(fileName, new DummyFilePathMapper(), settings, new NAMEContext());

                Assert.Equal(0, configuration.InfrastructureDependencies.Count());
                Assert.Equal(2, configuration.ServiceDependencies.Count());
                Assert.Equal(2, iterationsCount);

                var firstDependency  = (ConnectedDependency)configuration.ServiceDependencies.First();
                var secondDependency = (ConnectedDependency)configuration.ServiceDependencies.Skip(1).First();

                Assert.IsType <StaticConnectionStringProvider>(firstDependency.ConnectionStringProvider);
                Assert.IsType <StaticConnectionStringProvider>(secondDependency.ConnectionStringProvider);
            }
            finally
            {
                File.Delete(fileName);
            }
        }
예제 #5
0
        private static ParsedDependencies ParseDependenciesFromString(
            string jsonContents,
            IFilePathMapper pathMapper,
            NAMESettings settings,
            NAMEContext context)
        {
            JsonNode rootNode = Json.Json.Parse(jsonContents);

            return(new ParsedDependencies(
                       HandleDependencyArray(rootNode?["infrastructure_dependencies"]?.AsArray, pathMapper, settings, context),
                       HandleDependencyArray(rootNode?["service_dependencies"]?.AsArray, pathMapper, settings, context)));
        }
예제 #6
0
        public void ReadConfiguration_WithAllOverrides()
        {
            string fileContents = @"{
                ""$schema"": ""./config-manifest.schema.json"",
                ""Overrides"": {
                    ""RunningMode"": ""NAMEDisabled"",
                    ""RegistryEndpoints"": [
                          ""http://name:80/api"",
                          ""http://name2:80/api""
                    ],
                    ""SelfHostPortRangeFirst"": 1,
                    ""SelfHostPortRangeLast"": 10,
                    ""ServiceDependencyMaxHops"": 2,
                    ""ConnectedDependencyShowConnectionString"": false,
                    ""DependencyConnectTimeout"": 429496721,
                    ""DependencyReadWriteTimeout"": 429496722,
                    ""RegistryBootstrapRetryFrequency"": ""00.02:00:00"",
                    ""RegistryBootstrapTimeout"": ""00.00:00:31""
                },
                ""infrastructure_dependencies"": [
                ],
                ""service_dependencies"": [
                ]
            }";

            string fileName = Guid.NewGuid() + ".json";

            File.WriteAllText(fileName, fileContents);
            try
            {
                NAMESettings       settings      = DependenciesReader.ReadNAMESettingsOverrides(fileName, new DummyFilePathMapper());
                ParsedDependencies configuration = DependenciesReader.ReadDependencies(fileName, new DummyFilePathMapper(), settings, new NAMEContext());

                Assert.Equal(0, configuration.InfrastructureDependencies.Count());
                Assert.Equal(0, configuration.ServiceDependencies.Count());

                Assert.Equal(SupportedNAMEBehaviours.NAMEDisabled, settings.RunningMode);
                Assert.Equal(new[] { "http://name:80/api", "http://name2:80/api" }, settings.RegistryEndpoints);
                Assert.Equal(1, settings.SelfHostPortRangeFirst);
                Assert.Equal(10, settings.SelfHostPortRangeLast);
                Assert.Equal(2, settings.ServiceDependencyMaxHops);
                Assert.False(settings.ConnectedDependencyShowConnectionString);
                Assert.Equal(429496721, settings.DependencyConnectTimeout);
                Assert.Equal(429496722, settings.DependencyReadWriteTimeout);
                Assert.Equal(TimeSpan.FromHours(2), settings.RegistryBootstrapRetryFrequency);
                Assert.Equal(TimeSpan.FromSeconds(31), settings.RegistryBootstrapTimeout);
            }
            finally
            {
                File.Delete(fileName);
            }
        }
예제 #7
0
        /// <summary>
        /// Reads the configuration.
        /// </summary>
        /// <param name="dependenciesFile">The configuration file.</param>
        /// <param name="pathMapper">The path mapper.</param>
        /// <param name="settings">The settings.</param>
        /// <param name="context">The context.</param>
        /// <returns>
        /// Returns the dependencies read from the file.
        /// </returns>
        /// <exception cref="NAMEException">An unhandled exception happened.</exception>
        /// <exception cref="System.IO.FileNotFoundException">The configuration file was not found.</exception>
        public static ParsedDependencies ReadDependencies(
            string dependenciesFile,
            IFilePathMapper pathMapper,
            NAMESettings settings,
            NAMEContext context)
        {
            Guard.NotNull(settings, nameof(settings));
            if (context == null)
            {
                context = new NAMEContext();
            }

            string jsonContents = ReadJsonContents(pathMapper.MapPath(dependenciesFile));

            return(ParseDependenciesFromString(jsonContents, pathMapper, settings, context));
        }
예제 #8
0
        public void ReadConfiguration_UsesConnectionStringProviderReturnedFromOverride()
        {
            string fileContents = @"{
                ""infrastructure_dependencies"": [
                    {
                        ""type"": ""RabbitMq"",
                        ""name"": ""rabbitmq"",
                        ""min_version"": ""2.0"",
                        ""max_version"": ""3.3"",
                        ""connection_string"": {
                            ""locator"": ""JSONPath"",
                            ""key"": ""shouldn't matter""
                        }
                    }  
                ],
                ""service_dependencies"": [
                ]
            }";
            string fileName     = Guid.NewGuid() + ".json";

            File.WriteAllText(fileName, fileContents);
            try
            {
                int iterationsCount = 0;
                var settings        = new NAMESettings()
                {
                    ConnectionStringProviderOverride = (node) =>
                    {
                        iterationsCount++;
                        return(new StaticConnectionStringProvider(string.Empty));
                    }
                };

                ParsedDependencies configuration = DependenciesReader.ReadDependencies(fileName, new DummyFilePathMapper(), settings, new NAMEContext());

                Assert.Equal(1, configuration.InfrastructureDependencies.Count());
                Assert.Equal(0, configuration.ServiceDependencies.Count());
                Assert.Equal(1, iterationsCount);

                var firstDependency = (ConnectedDependency)configuration.InfrastructureDependencies.First();
                Assert.IsType <StaticConnectionStringProvider>(firstDependency.ConnectionStringProvider);
            }
            finally
            {
                File.Delete(fileName);
            }
        }
예제 #9
0
        /// <summary>
        /// Registers the instance in one or more registars.
        /// </summary>
        /// <param name="pathMapper">The path mapper.</param>
        /// <param name="apiName">Name of the API.</param>
        /// <param name="apiVersion">The API version.</param>
        /// <param name="dependenciesFileLocation">The dependencies file location.</param>
        /// <param name="settings">The context.</param>
        /// <param name="hostname">The hostname.</param>
        /// <param name="port">The port.</param>
        /// <param name="nameVersion">The name version.</param>
        /// <param name="nameEndpoint">The name endpoint.</param>
        /// <param name="supportedProtocols">The supported protocols.</param>
        /// <exception cref="System.ArgumentException">Too many dots. - nameVersion</exception>
        /// <exception cref="System.ArgumentNullException">nameConfig
        /// or
        /// hostname
        /// or
        /// vpath
        /// or
        /// nameVersion
        /// or
        /// nameEndpoint
        /// or
        /// supportedProtocols</exception>
        public void RegisterInstance(
            IFilePathMapper pathMapper,
            string apiName,
            string apiVersion,
            string dependenciesFileLocation,
            NAMESettings settings,
            string hostname,
            uint?port,
            string nameVersion,
            string nameEndpoint,
            params uint[] supportedProtocols)
        {
            this.pathMapper = Guard.NotNull(pathMapper, nameof(pathMapper));
            // todo guard
            this.settings           = Guard.NotNull(settings, nameof(settings));
            this.Hostname           = Guard.NotNull(hostname, nameof(hostname));
            this.NameVersion        = Guard.NotNull(nameVersion, nameof(nameVersion));
            this.NameEndpoint       = Guard.NotNull(nameEndpoint, nameof(nameEndpoint));
            this.SupportedProtocols = Guard.NotNull(supportedProtocols, nameof(supportedProtocols));

            this.dependenciesFileLocation = dependenciesFileLocation;
            this.ApiName    = apiName;
            this.ApiVersion = apiVersion;
            this.Hostname   = hostname;
            this.Port       = port;

            int dotsCount = nameVersion.Length - nameVersion.Replace(".", string.Empty).Length;

            if (dotsCount > 3)
            {
                throw new ArgumentException("Too many dots.", nameof(nameVersion));
            }

            this.NameVersion = nameVersion.Substring(0, nameVersion.LastIndexOf('.'));

            this.SupportedProtocols = supportedProtocols;

            if (this.settings.RegistryEndpoints.Length == 0)
            {
                LogInfo("No registry endpoints to register this api", true);
                return;
            }

            LogInfo("RegisterInstance started", true);

            this.RegisterTask = Task.Factory.StartNew(this.RegisterLoop, this.cancellationTokenSource.Token);
        }
예제 #10
0
        public bool Start(int port, NAMESettings settings)
        {
            try
            {
                this.settings = settings;

                this.httpListener = new SocketHttpListener.Net.HttpListener();
                this.httpListener.Prefixes.Add($"http://{this.nameConfiguration.AddressToListenOn}:{port}/{this.nameConfiguration.ManifestUriPrefix.TrimStart('/').TrimEnd('/')}/");
                this.httpListener.OnContext = this.OnContext;
                this.httpListener.Start();

                return(true);
            }
            catch (System.Net.HttpListenerException)
            {
                this.httpListener?.Stop();
                return(false);
            }
        }
예제 #11
0
        public async Task CheckDependencies_ConnectionStringFromOverride()
        {
            string contents =
                @"{
                ""$schema"": ""./config-manifest.schema.json"",
                ""infrastructure_dependencies"": [
                    {
                        ""type"": ""MongoDb"",
                        ""min_version"": ""2.6"",
                        ""max_version"": """ + Constants.SpecificMongoVersion + @""",
                        ""connection_string"": {
                            ""locator"": ""hard-coded""
                        }
                    }
                ],
                ""service_dependencies"": [
                ]
            }";
            string fileName = Guid.NewGuid() + ".json";

            File.WriteAllText(fileName, contents);
            try
            {
                var settings = new NAMESettings()
                {
                    ConnectionStringProviderOverride = (node) =>
                    {
                        if (node["locator"].Value == "hard-coded")
                        {
                            return(new StaticConnectionStringProvider("mongodb://" + Constants.SpecificMongoHostname + ":27017/nPVR_Dev_TST"));
                        }
                        return(null);
                    }
                };
                var parsedDependencies = DependenciesReader.ReadDependencies(fileName, new DummyFilePathMapper(), settings, new Core.NAMEContext());
                await DependenciesExtensions.CheckDependencies(parsedDependencies);
            }
            finally
            {
                File.Delete(fileName);
            }
        }
예제 #12
0
        public void ReadConfiguration_OperatingSystemDependency_SkipsOverride()
        {
            string fileContents = @"{
                ""infrastructure_dependencies"": [
                    {
                        ""os_name"": ""Ubuntu"",
                        ""type"": ""OperatingSystem"",
                        ""min_version"": ""16.04"",
                        ""max_version"": ""14.04""
                    }
                ],
                ""service_dependencies"": [
                ]
            }";
            string fileName     = Guid.NewGuid() + ".json";

            File.WriteAllText(fileName, fileContents);
            try
            {
                int iterationsCount = 0;
                var settings        = new NAMESettings()
                {
                    ConnectionStringProviderOverride = (node) =>
                    {
                        iterationsCount++;
                        return(null);
                    }
                };

                ParsedDependencies configuration = DependenciesReader.ReadDependencies(fileName, new DummyFilePathMapper(), settings, new NAMEContext());

                Assert.Equal(1, configuration.InfrastructureDependencies.Count());
                Assert.Equal(0, configuration.ServiceDependencies.Count());
                Assert.Equal(0, iterationsCount);
            }
            finally
            {
                File.Delete(fileName);
            }
        }
예제 #13
0
        /// <summary>
        /// Reads the dependencies.
        /// </summary>
        /// <param name="configurationStream">The configuration stream.</param>
        /// <param name="pathMapper">The path mapper.</param>
        /// <param name="settings">The context information.</param>
        /// <param name="context">The context.</param>
        /// <returns>
        /// Returns the dependencies read from the stream.
        /// </returns>
        /// <exception cref="NAMEException">Configuration file stream is not in readable state</exception>
        public static ParsedDependencies ReadDependencies(
            Stream configurationStream,
            IFilePathMapper pathMapper,
            NAMESettings settings,
            NAMEContext context)
        {
            Guard.NotNull(settings, nameof(settings));
            if (context == null)
            {
                context = new NAMEContext();
            }

            if (configurationStream.CanRead == false)
            {
                throw new NAMEException("Configuration file stream is not in readable state");
            }

            using (StreamReader reader = new StreamReader(configurationStream))
            {
                var jsonContents = reader.ReadToEnd();
                return(ParseDependenciesFromString(jsonContents, pathMapper, settings, context));
            }
        }
예제 #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NAMEMiddleware" /> class.
        /// </summary>
        /// <param name="next">The next middleware in the pipeline.</param>
        /// <param name="nameConfiguration">The name configuration.</param>
        /// <param name="settings">The name settings.</param>
        /// <param name="pathMapper">The path mapper.</param>
        public NAMEMiddleware(
            RequestDelegate next,
            NAMEBaseConfiguration nameConfiguration,
            NAMESettings settings,
            IFilePathMapper pathMapper)
        {
            this.next = next;
            this.nameConfiguration = nameConfiguration;
            this.settings          = settings;
            this.pathMapper        = pathMapper;


            if (string.IsNullOrEmpty(nameConfiguration.ManifestUriPrefix))
            {
                this.nameRequestMatcher   = new TemplateMatcher(TemplateParser.Parse(Constants.MANIFEST_ENDPOINT.TrimStart('/')), new RouteValueDictionary());
                this.nameUiRequestMatcher = new TemplateMatcher(TemplateParser.Parse(Constants.MANIFEST_UI_ENDPOINT.TrimStart('/')), new RouteValueDictionary());
            }
            else
            {
                this.nameRequestMatcher   = new TemplateMatcher(TemplateParser.Parse(nameConfiguration.ManifestUriPrefix.TrimEnd('/') + Constants.MANIFEST_ENDPOINT), new RouteValueDictionary());
                this.nameUiRequestMatcher = new TemplateMatcher(TemplateParser.Parse(nameConfiguration.ManifestUriPrefix.TrimEnd('/') + Constants.MANIFEST_UI_ENDPOINT), new RouteValueDictionary());
            }
        }
예제 #15
0
        private static IList <Dependency> HandleDependencyArray(
            JsonArray dependencies,
            IFilePathMapper pathMapper,
            NAMESettings configuration,
            NAMEContext context,
            int depth = 0)
        {
            IList <Dependency> handledDependencies = new List <Dependency>();

            if (dependencies == null)
            {
                return(handledDependencies);
            }

            foreach (JsonNode dependency in dependencies)
            {
                if (dependency.AsObject != null)
                {
                    handledDependencies.Add(HandleDependency(dependency.AsObject, pathMapper, configuration, context, depth));
                }
            }
            return(handledDependencies);
        }
예제 #16
0
 public NAMEUiHandler(NAMESettings settings)
 {
     this.settings = settings;
 }
예제 #17
0
        /// <summary>
        /// Reads the NAME settings overrides.
        /// </summary>
        /// <param name="settingsFile">The settings file.</param>
        /// <param name="pathMapper">The path mapper.</param>
        /// <returns>
        /// Returns the <see cref="NAMESettings" />.
        /// </returns>
        public static NAMESettings ReadNAMESettingsOverrides(string settingsFile, IFilePathMapper pathMapper)
        {
            Guard.NotNull(settingsFile, nameof(settingsFile));

            var jsonContents = ReadJsonContents(pathMapper.MapPath(settingsFile));

            JsonNode rootNode     = Json.Json.Parse(jsonContents);
            var      overrideNode = rootNode["Overrides"];

            var settings = new NAMESettings();

            if (overrideNode == null)
            {
                return(settings);
            }

            var registryEndpoints = overrideNode[nameof(settings.RegistryEndpoints)]?.AsArray;

            if (registryEndpoints != null)
            {
                settings.RegistryEndpoints = new string[registryEndpoints.Count];
                for (int i = 0; i < registryEndpoints.Count; i++)
                {
                    settings.RegistryEndpoints[i] = registryEndpoints[i].Value;
                }
            }

            var selfhostPortRangeFirst = overrideNode[nameof(settings.SelfHostPortRangeFirst)]?.AsInt;

            if (selfhostPortRangeFirst != null)
            {
                settings.SelfHostPortRangeFirst = selfhostPortRangeFirst.Value;
            }

            var selfhostPortRangeLast = overrideNode[nameof(settings.SelfHostPortRangeLast)]?.AsInt;

            if (selfhostPortRangeLast != null)
            {
                settings.SelfHostPortRangeLast = selfhostPortRangeLast.Value;
            }

            var serviceDependencyMaxHops = overrideNode[nameof(settings.ServiceDependencyMaxHops)]?.AsInt;

            if (serviceDependencyMaxHops != null)
            {
                settings.ServiceDependencyMaxHops = serviceDependencyMaxHops.Value;
            }

            var serviceDependencyShowConnectionString = overrideNode[nameof(settings.ConnectedDependencyShowConnectionString)]?.AsBool;

            if (serviceDependencyShowConnectionString != null)
            {
                settings.ConnectedDependencyShowConnectionString = serviceDependencyShowConnectionString.Value;
            }

            var dependencyConnectTimeout = overrideNode[nameof(settings.DependencyConnectTimeout)]?.AsInt;

            if (dependencyConnectTimeout != null)
            {
                settings.DependencyConnectTimeout = dependencyConnectTimeout.Value;
            }

            var dependencyReadWriteTimeout = overrideNode[nameof(settings.DependencyReadWriteTimeout)]?.AsInt;

            if (dependencyReadWriteTimeout != null)
            {
                settings.DependencyReadWriteTimeout = dependencyReadWriteTimeout.Value;
            }

            var registryReAnnounceFrequency = overrideNode[nameof(settings.RegistryReAnnounceFrequency)];

            if (registryReAnnounceFrequency != null && TimeSpan.TryParse(registryReAnnounceFrequency, out TimeSpan parsedAnnounceFreq))
            {
                settings.RegistryReAnnounceFrequency = parsedAnnounceFreq;
            }

            var registryPingFrequency = overrideNode[nameof(settings.RegistryPingFrequency)];

            if (registryPingFrequency != null && TimeSpan.TryParse(registryPingFrequency, out TimeSpan parsedPingFreq))
            {
                settings.RegistryPingFrequency = parsedPingFreq;
            }

            var runningMode = overrideNode[nameof(settings.RunningMode)];

            if (runningMode != null && Enum.TryParse <SupportedNAMEBehaviours>(runningMode.Value.ToString(), false, out var behaviour))
            {
                settings.RunningMode = behaviour;
            }

            var registryBootstrapRetryFrequency = overrideNode[nameof(settings.RegistryBootstrapRetryFrequency)];

            if (registryBootstrapRetryFrequency != null && TimeSpan.TryParse(registryBootstrapRetryFrequency, out TimeSpan bootstrapRetryFreq))
            {
                settings.RegistryBootstrapRetryFrequency = bootstrapRetryFreq;
            }

            var registryBootstrapConnectTimeout = overrideNode[nameof(settings.RegistryBootstrapTimeout)];

            if (registryBootstrapConnectTimeout != null && TimeSpan.TryParse(registryBootstrapConnectTimeout, out TimeSpan bootstrapConnectTimeout))
            {
                settings.RegistryBootstrapTimeout = bootstrapConnectTimeout;
            }

            return(settings);
        }
예제 #18
0
        private static IVersionResolver GetConnectedDependencyVersionResolver(SupportedDependencies dependencyType, IConnectionStringProvider connectionStringProvider, NAMESettings configuration, NAMEContext context)
        {
            switch (dependencyType)
            {
            case SupportedDependencies.MongoDb:
                return(new MongoDb.MongoDbVersionResolver(connectionStringProvider, configuration.DependencyConnectTimeout, configuration.DependencyReadWriteTimeout));

            case SupportedDependencies.RabbitMq:
                return(new RabbitMq.RabbitMqVersionResolver(connectionStringProvider, configuration.DependencyConnectTimeout, configuration.DependencyReadWriteTimeout));

            case SupportedDependencies.SqlServer:
                return(new SqlServer.SqlServerVersionResolver(connectionStringProvider, configuration.DependencyConnectTimeout, configuration.DependencyReadWriteTimeout));

            case SupportedDependencies.Service:
                return(new Service.ServiceVersionResolver(connectionStringProvider, context.ServiceDependencyCurrentNumberOfHops, configuration.ServiceDependencyMaxHops, configuration.DependencyConnectTimeout, configuration.DependencyReadWriteTimeout));

            default:
                throw new NAMEException($"The dependency of type {dependencyType} is not supported as a connected dependency.");
            }
        }
예제 #19
0
        private static Dependency HandleDependency(JsonClass dependency, IFilePathMapper pathMapper, NAMESettings configuration, NAMEContext context, int depth = 0)
        {
            if (depth == MAX_DEPENDENCY_DEPTH)
            {
                throw new NAMEException($"Reached the maximum dependency recursion of {MAX_DEPENDENCY_DEPTH}.");
            }

            if (dependency == null)
            {
                return(null);
            }
            var conditionObject = dependency["oneOf"];

            if (conditionObject != null)
            {
                depth++;
                return(new OneOfDependency(HandleDependencyArray(conditionObject.AsArray, pathMapper, configuration, context, depth)));
            }

            var minVersion = dependency["min_version"].Value;
            var maxVersion = dependency["max_version"].Value;
            var name       = dependency["name"]?.Value;
            var type       = dependency["type"]?.Value;
            var osName     = dependency["os_name"]?.Value;

            type = string.IsNullOrEmpty(type) ? SupportedDependencies.Service.ToString() : type;
            SupportedDependencies typedType;

            if (!Enum.TryParse(type, out typedType))
            {
                throw new NAMEException($"The dependency type {type} is not supported.");
            }

            VersionedDependency result;

            if (typedType == SupportedDependencies.OperatingSystem)
            {
                result = new OperatingSystemDependency()
                {
                    OperatingSystemName = osName,
                    MinimumVersion      = ParseVersion(minVersion, osName),
                    MaximumVersion      = ParseVersion(maxVersion, osName)
                };
            }
            else
            {
                var connectionStringProvider = ParseConnectionStringProvider(dependency["connection_string"], pathMapper);
                result = new ConnectedDependency(GetConnectedDependencyVersionResolver(typedType, connectionStringProvider, configuration, context))
                {
                    ConnectionStringProvider   = connectionStringProvider,
                    MinimumVersion             = ParseVersion(minVersion, type),
                    MaximumVersion             = ParseVersion(maxVersion, type),
                    ShowConnectionStringInJson = configuration.ConnectedDependencyShowConnectionString
                };
            }

            result.Name = name;
            result.Type = typedType;
            return(result);
        }
예제 #20
0
        /// <summary>
        /// Reads the and log dependencies.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <param name="logToConsole">if set to <c>true</c> [log to console].</param>
        /// <param name="pathMapper">The path mapper.</param>
        /// <param name="settings">The context information.</param>
        /// <returns>
        /// The <see cref="ParsedDependencies" /> object populated from the dependencies file
        /// </returns>
        /// <exception cref="NAMEException">Error parsing the dependencies file.</exception>
        /// <exception cref="DependenciesCheckException">Wrapper for all possible exceptions in the NAME process</exception>
        public static ParsedDependencies ReadAndLogDependencies(NAMEBaseConfiguration configuration, bool logToConsole, IFilePathMapper pathMapper, out NAMESettings settings)
        {
            var dependencies = new ParsedDependencies(null, null);

            settings = DependenciesReader.ReadNAMESettingsOverrides(configuration.DependenciesFilePath, pathMapper);

            try
            {
                dependencies = DependenciesReader.ReadDependencies(configuration.DependenciesFilePath, pathMapper, settings, new NAMEContext());
            }
            catch (NAMEException ex)
            {
                LogWarning($"Could not parse the dependencies file: {ex.Message}.", logToConsole);
                if (configuration.ThrowOnDependenciesFail)
                {
                    if (ex is NAMEException)
                    {
                        throw;
                    }
                    else
                    {
                        throw new NAMEException("Error parsing the dependencies file.", ex, NAMEStatusLevel.Error);
                    }
                }
                return(dependencies);
            }

            if (settings.RunningMode == SupportedNAMEBehaviours.NAMEDisabled)
            {
                LogInfo("NAME was disabled in the dependencies file.", logToConsole);
                return(dependencies);
            }

            LogInfo("Starting the dependencies state logs.", logToConsole);

            Func <IEnumerable <DependencyCheckStatus> > logStatusesAction = () =>
            {
                var allStatuses = LogDependenciesStatuses(dependencies.InfrastructureDependencies, logToConsole);
                allStatuses.AddRange(LogDependenciesStatuses(dependencies.ServiceDependencies, logToConsole));
                return(allStatuses);
            };

            if (configuration.ThrowOnDependenciesFail)
            {
                var allStatuses = logStatusesAction();
                if (allStatuses.Any(s => s.CheckStatus != NAMEStatusLevel.Ok))
                {
                    throw new DependenciesCheckException(allStatuses);
                }
            }
            else
            {
                Task.Factory
                .StartNew(logStatusesAction)
                .ContinueWith(
                    task =>
                {
                    LogWarning("Exception logging dependencies status:", logToConsole);
                    var flattened = task.Exception.Flatten();
                    flattened.Handle(ex =>
                    {
                        LogWarning(ex.Message, logToConsole);
                        return(true);
                    });
                },
                    TaskContinuationOptions.OnlyOnFaulted);
            }

            return(dependencies);
        }
예제 #21
0
 /// <summary>
 /// Determines if the manifest endpoint should be enabled considering the current <see cref="NAMESettings"/> state.
 /// </summary>
 /// <param name="nameSettings">The NAME settings.</param>
 /// <returns>Returns true if the endpoint should be enabled.</returns>
 public static bool IsManifestEndpointEnabled(this NAMESettings nameSettings)
 {
     return(nameSettings.RunningMode != SupportedNAMEBehaviours.NAMEDisabled);
 }
예제 #22
0
        /// <summary>
        /// Reads the and log dependencies.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <param name="logToConsole">if set to <c>true</c> [log to console].</param>
        /// <param name="pathMapper">The path mapper.</param>
        /// <param name="settings">The context information.</param>
        /// <returns>
        /// The <see cref="ParsedDependencies" /> object populated from the dependencies file
        /// </returns>
        /// <exception cref="NAMEException">Error parsing the dependencies file.</exception>
        /// <exception cref="DependenciesCheckException">Wrapper for all possible exceptions in the NAME process</exception>
        public static ParsedDependencies ReadAndLogDependencies(NAMEBaseConfiguration configuration, bool logToConsole, IFilePathMapper pathMapper, out NAMESettings settings)
        {
            var dependencies = new ParsedDependencies(null, null);

            settings = DependenciesReader.ReadNAMESettingsOverrides(configuration.DependenciesFilePath, pathMapper);

            try
            {
                dependencies = DependenciesReader.ReadDependencies(configuration.DependenciesFilePath, pathMapper, settings, new NAMEContext());
            }
            catch (NAMEException ex)
            {
                LogWarning($"Could not parse the dependencies file: {ex.Message}.", logToConsole);
                if (configuration.ThrowOnDependenciesFail)
                {
                    if (ex is NAMEException)
                    {
                        throw;
                    }
                    else
                    {
                        throw new NAMEException("Error parsing the dependencies file.", ex);
                    }
                }
                return(dependencies);
            }

            if (settings.RunningMode == SupportedNAMEBehaviours.NAMEDisabled)
            {
                LogInfo("NAME was disabled in the dependencies file.", logToConsole);
                return(dependencies);
            }

            LogInfo("Starting the dependencies state logs.", logToConsole);

            var allStatuses = LogDependenciesStatuses(dependencies.InfrastructureDependencies, logToConsole);

            allStatuses.AddRange(LogDependenciesStatuses(dependencies.ServiceDependencies, logToConsole));

            if (configuration.ThrowOnDependenciesFail && allStatuses.Any(s => !s.CheckPassed))
            {
                throw new DependenciesCheckException(allStatuses);
            }

            return(dependencies);
        }
예제 #23
0
 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
 public void Configure(IApplicationBuilder app, IFilePathMapper pathMapper, NAMEKestrelConfiguration configuration, NAMESettings settings)
 {
     app.UseMiddleware <NAMEMiddleware>(configuration, settings, pathMapper);
 }