private async Task LoadAsync()
        {
            var data = (IDictionary <string, string>) new Dictionary <string, string>();

            try
            {
                if (!_elements.Any())
                {
                    return;
                }

                await using (var stream = new MemoryStream())
                {
                    await using (var sw = new StreamWriter(stream))
                    {
                        using (var writer = new XmlNoNamespaceWriter(sw, new XmlWriterSettings {
                            CloseOutput = false
                        }))
                        {
                            foreach (var element in _elements)
                            {
                                element.Save(writer);
                            }

                            writer.Flush();
                            await sw.FlushAsync();

                            data = XmlStreamToDictionaryParser.Parse(stream, options =>
                            {
                                options.IsIndexAttribute = (attribute, stack) =>
                                {
                                    switch (stack.FirstOrDefault())
                                    {
                                    case "Endpoint": return(string.Equals(attribute, "Id", StringComparison.OrdinalIgnoreCase));

                                    case "Route": return(string.Equals(attribute, "RouteId", StringComparison.OrdinalIgnoreCase));
                                    }
                                    return(false);
                                };
                            }
                                                                     );
                        }
                    }
                }
            }
            finally
            {
                Data = data;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Gets the labels from the extensions of the provided raw service manifest.
        /// </summary>
        private async Task <IDictionary <string, string> > ExtractLabelsAsync(
            string rawServiceManifest,
            string targetServiceTypeName,
            CancellationToken cancellationToken)
        {
            using (var reader = XmlReader.Create(new StringReader(rawServiceManifest),
                                                 CreateSafeXmlSetting(1024 * 1024, 1024)))
            {
                XDocument parsedManifest;
                try
                {
                    parsedManifest = await XDocument.LoadAsync(reader, LoadOptions.None, cancellationToken);
                }
                catch (System.Xml.XmlException ex)
                {
                    // TODO: we don't know if the service wants to use the gateway yet, so not sure if this classifies as config error (considering it will escalate into a bad health report)
                    throw new ConfigException("Failed to parse service manifest XML.", ex);
                }

                var elements = parsedManifest
                               .Elements(XNSServiceManifest + "ServiceManifest")
                               .Elements(XNSServiceManifest + "ServiceTypes")
                               .Elements().Where(s => (string)s.Attribute("ServiceTypeName") == targetServiceTypeName)
                               .Elements(XNSServiceManifest + "Extensions")
                               .Elements(XNSServiceManifest + "Extension").Where(s => (string)s.Attribute("Name") == ConfigurationValues.ExtensionName)
                               .Elements(XNSFabricNoSchema + "Service");

                if (!elements.Any())
                {
                    return(new Dictionary <string, string>());
                }

                await using (var stream = new MemoryStream())
                {
                    await using (var sw = new StreamWriter(stream))
                    {
                        using (var writer = new XmlNoNamespaceWriter(sw, new XmlWriterSettings {
                            CloseOutput = false
                        }))
                        {
                            foreach (var element in elements)
                            {
                                element.Save(writer);
                            }

                            writer.Flush();
                            await sw.FlushAsync();

                            var labels = XmlStreamToDictionaryParser.Parse(stream, (options) =>
                            {
                                options.KeyDelimiter = ".";
                                options.Parents      = new List <string> {
                                    "Service"
                                };
                                options.IsIndexAttribute = (attribute, stack) =>
                                {
                                    switch (stack.FirstOrDefault())
                                    {
                                    case "Endpoint": return(string.Equals(attribute, "Id", StringComparison.OrdinalIgnoreCase));

                                    case "Route": return(string.Equals(attribute, "Id", StringComparison.OrdinalIgnoreCase));
                                    }
                                    return(false);
                                };
                            });
                            return(labels);
                        }
                    }
                }
            }
        }
Beispiel #3
0
        private async Task LoadServiceDataAsync(Dictionary <string, string> data, ApplicationWrapper application, string appPrefix,
                                                ServiceWrapper service, CancellationToken cancellationToken)
        {
            string serviceManifestName;

            try
            {
                serviceManifestName = await _serviceFabricCaller.GetServiceManifestName(application.ApplicationTypeName,
                                                                                        application.ApplicationTypeVersion, service.ServiceTypeName, cancellationToken);
            }
            catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
            {
                throw;
            }
            catch (Exception ex) // TODO: davidni: not fatal?
            {
                throw new ServiceFabricIntegrationException(
                          $"Failed to get service manifest name for service type {service.ServiceTypeName} of application type {application.ApplicationTypeName} {application.ApplicationTypeVersion} from Service Fabric: {ex}.");
            }

            if (serviceManifestName == null)
            {
                throw new ServiceFabricIntegrationException(
                          $"No service manifest name was found for service type {service.ServiceTypeName} of application type {application.ApplicationTypeName} {application.ApplicationTypeVersion}.");
            }

            string rawServiceManifest;

            try
            {
                rawServiceManifest = await _serviceFabricCaller.GetServiceManifestAsync(application.ApplicationTypeName,
                                                                                        application.ApplicationTypeVersion, serviceManifestName, cancellationToken);
            }
            catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
            {
                throw;
            }
            catch (Exception ex) // TODO: davidni: not fatal?
            {
                throw new ServiceFabricIntegrationException(
                          $"Failed to get service manifest {serviceManifestName} of service type {service.ServiceTypeName} of application type {application.ApplicationTypeName} {application.ApplicationTypeVersion} from Service Fabric: {ex}.");
            }

            if (rawServiceManifest == null)
            {
                throw new ServiceFabricIntegrationException(
                          $"No service manifest named '{serviceManifestName}' was found for service type {service.ServiceTypeName} of application type {application.ApplicationTypeName} {application.ApplicationTypeVersion}.");
            }

            using (var reader = XmlReader.Create(new StringReader(rawServiceManifest), XmlReaderHelper.CreateSafeXmlSetting()))
            {
                XDocument parsedManifest;
                try
                {
                    parsedManifest = await XDocument.LoadAsync(reader, LoadOptions.None, cancellationToken);
                }
                catch (System.Xml.XmlException ex)
                {
                    // TODO: we don't know if the service wants to use the gateway yet, so not sure if this classifies as config error (considering it will escalate into a bad health report)
                    throw new ConfigException("Failed to parse service manifest XML.", ex);
                }

                var elements = parsedManifest
                               .Elements(XmlReaderHelper.XNSServiceManifest + "ServiceManifest")
                               .Elements(XmlReaderHelper.XNSServiceManifest + "ServiceTypes")
                               .Elements().Where(s => (string)s.Attribute("ServiceTypeName") == service.ServiceTypeName)
                               .Elements(XmlReaderHelper.XNSServiceManifest + "Extensions")
                               .Elements(XmlReaderHelper.XNSServiceManifest + "Extension").Where(s =>
                                                                                                 (string)s.Attribute("Name") == ConfigurationValues.ExtensionName)
                               .Elements(XmlReaderHelper.XNSFabricNoSchema + "Service");

                if (!elements.Any())
                {
                    return;
                }

                var serviceId     = service.ServiceName.ToString().Replace($"{application.ApplicationName}/", string.Empty);
                var servicePrefix =
                    $"{appPrefix}Services{ConfigurationPath.KeyDelimiter}{serviceId}{ConfigurationPath.KeyDelimiter}";
                data[$"{servicePrefix}Id"]              = serviceId;
                data[$"{servicePrefix}Name"]            = service.ServiceName.ToString();
                data[$"{servicePrefix}TypeName"]        = service.ServiceTypeName;
                data[$"{servicePrefix}Kind"]            = service.ServiceKind.ToString();
                data[$"{servicePrefix}ManifestVersion"] = service.ServiceManifestVersion;

                await using (var stream = new MemoryStream())
                {
                    await using (var sw = new StreamWriter(stream))
                    {
                        using (var writer = new XmlNoNamespaceWriter(sw, new XmlWriterSettings {
                            CloseOutput = false
                        }))
                        {
                            foreach (var element in elements)
                            {
                                element.Save(writer);
                            }

                            writer.Flush();
                            await sw.FlushAsync();

                            var sections = XmlStreamToDictionaryParser.Parse(stream, (options) =>
                            {
                                options.KeyDelimiter = ConfigurationPath.KeyDelimiter;
                                options.Parents      = new List <string>(servicePrefix.Split(ConfigurationPath.KeyDelimiter,
                                                                                             StringSplitOptions.RemoveEmptyEntries));
                                options.IsIndexAttribute = (attribute, stack) =>
                                {
                                    switch (stack.FirstOrDefault())
                                    {
                                    case "Endpoint":
                                        return(string.Equals(attribute, "Id", StringComparison.OrdinalIgnoreCase));

                                    case "Route":
                                        return(string.Equals(attribute, "Id", StringComparison.OrdinalIgnoreCase));
                                    }

                                    return(false);
                                };
                            });
                            foreach (var section in sections)
                            {
                                data[section.Key] = section.Value;
                            }
                        }
                    }
                }
            }
        }