/// <summary> /// Saves the configuration root entity to the durable cache. /// </summary> /// <param name="config">The node to store</param> protected void SaveConfigToCache(ConfigRoot config) { IJsonEntity<ConfigRoot> configEntity = _cacheProvider.Entities.FirstOrDefault(y => y.Contents.ComponentName == _componentName); if (configEntity == null) { configEntity = _cacheProvider.Create(); } configEntity.Contents = config; _cacheProvider.Update(configEntity); _cacheProvider.Save(); }
public void Put_on_empty_repo_returns_404() { var configRoot = new ConfigRoot { ComponentName = "tabouli", Data = new ConfigNode { Name = "tabouli", Value = "tomatoes", Children = new List<ConfigNode> { new ConfigNode { Name = "Side", Value = "Rice" } } } }; IRequest request = new InMemoryRequest { HttpMethod = "PUT", Uri = new Uri("http://localhost/Config/tacos") }; request.Headers["Content-Type"] = "application/json"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(404, response.StatusCode); }
public void Put_with_invalid_content_type_returns_415() { var entity = _repository.Create(); entity.Contents = new ConfigRoot { ComponentName = "taboUli", Data = new ConfigNode { Name = "tabouli", Value = "salad" } }; _repository.Add(entity); _repository.Save(); var configRoot = new ConfigRoot { ComponentName = "tabouLi", Data = new ConfigNode { Name = "tabouli", Value = "tomatoes", Children = new List<ConfigNode> { new ConfigNode { Name = "Side", Value = "Rice" } } } }; IRequest request = new InMemoryRequest { HttpMethod = "PUT", Uri = new Uri("http://localhost/Config/tabouli") }; request.Headers["Content-Type"] = "text/plain"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(415, response.StatusCode); }
public void If_an_attempt_is_made_to_change_a_name_using_put_make_sure_it_doesnt_overwrite_something_else() { var entity = _repository.Create(); entity.Contents = new ConfigRoot { ComponentName = "taBouli", Data = new ConfigNode {Name = "tabouli", Value = "salad"} }; _repository.Add(entity); var anotherEntity = _repository.Create(); anotherEntity.Contents = new ConfigRoot { ComponentName = "Grapes", Data = new ConfigNode {Name = "grapes", Value = "wrath"} }; _repository.Add(anotherEntity); _repository.Save(); var configRoot = new ConfigRoot { ComponentName = "grapeS", Data = new ConfigNode { Name = "taboulI", Value = "tomatoes", Children = new List<ConfigNode> {new ConfigNode {Name = "Side", Value = "Rice"}} } }; IRequest request = new InMemoryRequest { HttpMethod = "PUT", Uri = new Uri("http://localhost/Config/tabouli") }; request.Headers["Content-Type"] = "application/json"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(409, response.StatusCode); }
public void Put_updates_config_root_in_repository() { var entity = _repository.Create(); entity.Contents = new ConfigRoot { ComponentName = "taboUli", Data = new ConfigNode {Name = "tabouli", Value = "salad"} }; _repository.Add(entity); _repository.Save(); var configRoot = new ConfigRoot { ComponentName = "tabouLi", Data = new ConfigNode { Name = "tabouli", Value = "tomatoes", Children = new List<ConfigNode> {new ConfigNode {Name = "Side", Value = "Rice"}} } }; IRequest request = new InMemoryRequest { HttpMethod = "PUT", Uri = new Uri("http://localhost/Config/tabouli") }; request.Headers["Content-Type"] = "application/json"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(200, response.StatusCode); var configObj = GetConfigRootFromResponseStream(response.Entity.Stream); Assert.IsNotNull(configObj); Assert.AreEqual("tabouli", configObj.ComponentName.ToLower()); Assert.AreEqual("tomatoes", configObj.Data.Value); Assert.AreEqual("Rice", configObj.Data.Children[0].Value); }
public void Post_returns_400_if_component_name_is_null() { var configRoot = new ConfigRoot { ComponentName = null, Data = new ConfigNode { Name = string.Empty, Value = string.Empty } }; IRequest request = new InMemoryRequest { HttpMethod = "POST", Uri = new Uri("http://localhost/Config") }; request.Headers["Content-Type"] = "application/json"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(400, response.StatusCode); }
private ConfigRoot CreateCannedEnvironmentConfig() { ConfigRoot config = new ConfigRoot { ComponentName = "Environment", LastModified = TestDate }; config.Data = new ConfigNode { Name = "Environment", Children = new List<ConfigNode> { new ConfigNode {Name = "RestUrl", Value = _expectedConfig.RestUrl}, new ConfigNode {Name = "ConnectionString", Value = _expectedConfig.ConnectionString}, } }; return config; }
private long WriteConfigRootToStream(Stream stream, ConfigRoot configRoot) { using (var sw = new StreamWriter(stream)) { sw.Write(JsonConvert.SerializeObject(configRoot)); } stream.Position = 0; return stream.Length; }
private static HttpResponseMessage CreateGoodResponseForSaveOrGetComponent(ConfigRoot configRoot) { string jsonString = JsonConvert.SerializeObject(configRoot); var response = new HttpResponseMessage(HttpStatusCode.OK); response.Content = new StringContent(jsonString, Encoding.UTF8, JsonMediaType); return response; }
public static ConfigRoot GetConfigRoot(string componentName) { ConfigRoot root = new ConfigRoot(); root.ComponentName = componentName; root.LastModified = new DateTime(2009, 11, 14); var node = new ConfigNode(); node.Name = root.ComponentName; node.Children = new List<ConfigNode> { new ConfigNode {Name = "N1", Value = "V1"}, new ConfigNode {Name = "N2", Value = "V2"} }; root.Data = node; return root; }
/// <summary> /// Performs an update on an existing Config resource and returns a copy of the saved data if successful. /// </summary> /// <param name="componentName">The name of the resource to update. Not case-sensitive.</param> /// <param name="config">The new config data to store - overwrites any exsiting data</param> /// <returns> /// 200 - If update is successful /// 409 - If an attempt is made to change the name of an existing resource and that name change would cause it to overwrite another resource (see remarks) /// 404 - If the requested resource does not exist /// </returns> /// <remarks> /// This operation allows resource renaming. If you change the component name in the config JSON, when the operation completes the resource will have a /// new Location returned in the headers, provided that no other resource exists with the same name. /// </remarks> public OperationResult Put(string componentName, ConfigRoot config) { _log.Debug("Entering ConfigHandler.Put()"); try { var requestedEntity = _repository.Entities.FirstOrDefault( x => x.Contents.ComponentName.ToUpper() == componentName.ToUpper()); if (requestedEntity == null) { _log.Debug(string.Format("Returning 404 Not Found for resource {0}", componentName)); return new OperationResult.NotFound(); } if (config.ComponentName == null || Regex.IsMatch(config.ComponentName, @"\W")) { return new OperationResult.BadRequest(); } IJsonEntity<ConfigRoot> existingEntity = _repository.Entities.FirstOrDefault( x => x.Contents.ComponentName.ToUpper() == config.ComponentName.ToUpper()); if (existingEntity != null && config.ComponentName.ToUpper() != componentName.ToUpper()) { _log.Debug( string.Format( "Returning 409 Conflict for resource {0} - attempted to change name to existing resource {1}", componentName, config.ComponentName)); return new ConflictOperationResult(); } requestedEntity.Contents = config; _repository.Update(requestedEntity); _repository.Save(); var location = HttpHelper.GetLocation(_request.Uri, config.ComponentName); _response.Headers[HttpHelper.LocationHeader] = location.ToString(); return new OperationResult.OK {ResponseResource = requestedEntity.Contents}; } catch (Exception exception) { _log.Error(string.Format("Error in Put for component '{0}': {1}", componentName, exception)); throw; } }
/// <summary> /// Handles POST for creating new resource. /// </summary> /// <param name="config">Config root deserialized from JSON in request body</param> /// <returns> /// 409 Conflict - If config exists for component of same name already in repository /// 201 Created - If adding new config succeeds /// 500 Internal Server Error - If error occurs /// </returns> public OperationResult Post(ConfigRoot config) { _log.Debug("Entering ConfigHandler.Post()"); try { IJsonEntity<ConfigRoot> configEntity = _repository.Entities.FirstOrDefault( x => x.Contents.ComponentName.ToLower() == config.ComponentName.ToLower()); if (configEntity != null) { _log.Debug(string.Format("Returning 400 Bad Request for POST to component {0}", config.ComponentName)); return new OperationResult.BadRequest(); } if (config.ComponentName == null || Regex.IsMatch(config.ComponentName, @"\W")) { _log.Debug(string.Format("Returning 400 Bad Request for POST to component {0}", config.ComponentName)); return new OperationResult.BadRequest(); } configEntity = _repository.Create(); configEntity.Contents = config; _repository.Add(configEntity); _repository.Save(); var location = HttpHelper.GetLocation(_request.Uri, config.ComponentName); _response.Headers[HttpHelper.LocationHeader] = location.ToString(); return new OperationResult.Created {ResponseResource = configEntity.Contents}; } catch (Exception exception) { _log.Error(string.Format("Error in Post for component '{0}': {1}", config != null ? config.ComponentName : null, exception)); throw; } }
private void CreateMockDurableCacheEntry(ConfigRoot configFromMockCache) { DurableMemoryRepositoryHelper.CreateMockDurableCacheEntry(configFromMockCache, _mockFileSystem, 1, TestPath); }
private ConfigRoot CreateCannedApplicationConfig() { ConfigRoot config = new ConfigRoot {ComponentName = _applicationConfigProvider.ApplicationComponentName, LastModified = TestDate}; config.Data = new ConfigNode { Name = _applicationConfigProvider.ApplicationComponentName, Children = new List<ConfigNode> { new ConfigNode {Name = "TimeOut", Value = _expectedConfig.Timeout.ToString()}, new ConfigNode { Name = "ConfigObject", Children = new List<ConfigNode> { new ConfigNode {Name = "Name", Value = "Taco"}, new ConfigNode {Name = "Number", Value = "6"} } } } }; return config; }
public void Ensure_that_error_handling_works_for_put() { // Override the config to give it a broken logger /*var mockLogger = new Mock<ILog>(); mockLogger.Setup(s => s.Debug(It.Is<string>(m => m.Contains("Entering ConfigHandler")))) .Throws(new ApplicationException("ha ha!"));*/ _mockFileSystem = (new MockFileSystemProvider()).MockFileSystem; _repository = new DurableMemoryRepository<ConfigRoot>(DataPath, _mockFileSystem.Object); var container = new Container(); container.Configure(x => { x.For<IRepository<IJsonEntity<ConfigRoot>>>().Singleton().Use(_repository); //x.For<ILog>().Singleton().Use(mockLogger.Object); }); _host = new InMemoryHost(new Configuration(container)); var configRoot = new ConfigRoot { ComponentName = "tabOuli", Data = new ConfigNode { Name = "tabouli", Value = "tomatoes", Children = new List<ConfigNode> { new ConfigNode { Name = "Side", Value = "Rice" } } } }; IRequest request = new InMemoryRequest { HttpMethod = "PUT", Uri = new Uri("http://localhost/Config/tacos") }; request.Headers["Content-Type"] = "application/json"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(500, response.StatusCode); }
public void Put_returns_400_if_component_name_contains_invalid_characters() { var entity = _repository.Create(); entity.Contents = new ConfigRoot { ComponentName = "taboUli", Data = new ConfigNode { Name = "tabouli", Value = "salad" } }; _repository.Add(entity); _repository.Save(); var configRoot = new ConfigRoot { ComponentName = "jsnsadnc sd 8d8*** sad8s7sagd ^Q^ G5asds", Data = new ConfigNode { Name = string.Empty, Value = string.Empty } }; IRequest request = new InMemoryRequest { HttpMethod = "PUT", Uri = new Uri("http://localhost/Config/tabouli") }; request.Headers["Content-Type"] = "application/json"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(400, response.StatusCode); }
private static HttpResponseMessage CreateGoodResponseForAddNewComponent(ConfigRoot root) { string jsonString = JsonConvert.SerializeObject(root); var response = new HttpResponseMessage(HttpStatusCode.Created); response.Headers.Add("location", String.Format("http://config/{0}", root.ComponentName)); response.Content = new StringContent(jsonString, Encoding.UTF8, JsonMediaType); return response; }
public void Post_to_existing_component_config_returns_400() { // add tabouli to repo var entity = _repository.Create(); entity.Contents = new ConfigRoot { ComponentName = "tabouli", Data = new ConfigNode {Name = "host", Value = "tortilla"} }; _repository.Add(entity); _repository.Save(); // create new tabouli config to POST var configRoot = new ConfigRoot { ComponentName = "tabouli", Data = new ConfigNode { Name = "tabouli", Value = "tomatoes", Children = new List<ConfigNode> {new ConfigNode {Name = "Side", Value = "Rice"}} } }; IRequest request = new InMemoryRequest { HttpMethod = "POST", Uri = new Uri("http://localhost/Config") }; request.Headers["Content-Type"] = "application/json"; var length = WriteConfigRootToStream(request.Entity.Stream, configRoot); request.Headers["Content-Length"] = length.ToString(CultureInfo.InvariantCulture); var response = _host.ProcessRequest(request); Assert.AreEqual(400, response.StatusCode); }
/// <summary> /// Builds a factory that knows how to create a Config Provider that acts like the real thing, but doesn't use real caches or service calls. /// </summary> /// <param name="applicationConfig">The canned application configuration that the provider should use</param> /// <param name="environmentConfig">The canned environment configuration that the provider should use</param> /// <returns>A mock factory</returns> private Mock<IConfigProviderFactory> CreateFactory(ConfigRoot applicationConfig, ConfigRoot environmentConfig) { var mockConfigServiceProviderForApplication = new Mock<IConfigServiceProvider>(MockBehavior.Strict); var cannedApplicationResponse = new ConfigServiceResponse { Config = applicationConfig, StatusCode = HttpStatusCode.OK }; mockConfigServiceProviderForApplication.Setup(x => x.GetConfig()).Returns(cannedApplicationResponse); var mockApplicationConfig = new Mock<IJsonEntity<ConfigRoot>>(MockBehavior.Strict); mockApplicationConfig.SetupProperty(x => x.Contents); mockApplicationConfig.SetupProperty(x => x.JsonData); mockApplicationConfig.Object.Contents = applicationConfig; var mockConfigServiceProviderForEnvironment = new Mock<IConfigServiceProvider>(MockBehavior.Strict); var cannedEnvironmentResponse = new ConfigServiceResponse { Config = environmentConfig, StatusCode = HttpStatusCode.OK }; mockConfigServiceProviderForEnvironment.Setup(x => x.GetConfig()).Returns(cannedEnvironmentResponse); var mockEnvironmentConfig = new Mock<IJsonEntity<ConfigRoot>>(MockBehavior.Strict); mockEnvironmentConfig.SetupProperty(x => x.Contents); mockEnvironmentConfig.SetupProperty(x => x.JsonData); mockEnvironmentConfig.Object.Contents = environmentConfig; var mockFactory = new Mock<IConfigProviderFactory>(MockBehavior.Strict); var cacheProvider = new Mock<IRepository<IJsonEntity<ConfigRoot>>>(MockBehavior.Strict); cacheProvider.SetupAllProperties(); cacheProvider.SetupGet(x => x.Entities).Returns(new[] {mockApplicationConfig.Object, mockEnvironmentConfig.Object}.AsQueryable()); cacheProvider.Setup(x => x.Save()); cacheProvider.Setup(x => x.Update(It.IsAny<IJsonEntity<ConfigRoot>>())); mockFactory.Setup( x => x.Create(_applicationConfigProvider.ApplicationComponentName, It.IsAny<Dictionary<string, Func<string, bool>>>())) .Returns<string, Dictionary<string, Func<string, bool>>>((name, validators) => { return new ConfigProvider(name, validators, mockConfigServiceProviderForApplication.Object, cacheProvider.Object); }); mockFactory.Setup( x => x.Create("Environment", It.IsAny<Dictionary<string, Func<string, bool>>>())) .Returns<string, Dictionary<string, Func<string, bool>>>((name, validators) => { return new ConfigProvider(name, validators, mockConfigServiceProviderForEnvironment.Object, cacheProvider.Object); }); return mockFactory; }