Skip to content

Commit

Permalink
Move location route
Browse files Browse the repository at this point in the history
  • Loading branch information
juzuluag committed Jan 10, 2023
1 parent 7ffc45e commit 0942c07
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 63 deletions.
4 changes: 2 additions & 2 deletions docs/carbon-aware-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The CLI exposes the primary `getEmissionsByLocationsAndTime` SDK methods via com
- [Single Location Emissions](#single-location-emissions)
- [Multiple Location Emissions](#multiple-location-emissions)
- [Emissions with Start and End Times](#emissions-with-start-and-end-times)
- [Emissions Locations](#emissions-locations)
- [Locations](#locations)

## Build and Install

Expand Down Expand Up @@ -366,7 +366,7 @@ output:
}]
```

##### Emissions Locations
##### Locations

command: `.\caw locations`

Expand Down
13 changes: 10 additions & 3 deletions docs/carbon-aware-webapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The WebApi replicates the CLI and SDK functionality, leveraging the same configu
- [POST emissions/forecasts/batch](#post-emissionsforecastsbatch)
- [GET emissions/average-carbon-intensity](#get-emissionsaverage-carbon-intensity)
- [POST emissions/average-carbon-intensity/batch](#post-emissionsaverage-carbon-intensitybatch)
- [GET emissions/locations](#get-emissionslocations)
- [GET /locations](#get-locations)
- [Error Handling](#error-handling)
- [Autogenerate WebAPI](#autogenerate-webapi)
- [Data Sources](#data-sources)
Expand Down Expand Up @@ -317,7 +317,7 @@ The response is an array of CarbonIntensityDTO objects which each have a locatio
]
```

### GET emissions/locations
### GET /locations

This endpoint lists all the supported locations that the datasources potentially can have access to. This information is coming from the `location-source/json` files, that contain dictionaries in the form of <A Location key name, GeoCoordinates>, for instance:

Expand Down Expand Up @@ -358,7 +358,14 @@ This endpoint lists all the supported locations that the datasources potentially
}
```

If there is a third file with the same key name, it would be `swedencentral_2` and so on. This information is not persisted, but now the user can make requests using `swedencentral` and/or `swedencentral_1`.
If there is a third file with the same key name, it would be `swedencentral_2` and so on. This information is not persisted, but now the user can make requests using `swedencentral` and/or `swedencentral_1`. Also there are log ***warning*** entries when this scenerario occurs to help the user to understand what key renaming happened.

```sh
warn: Location key swedencentral from ... already exists. Creating new key.
...
warn: New key swedencentral_1 generated from swedencentral
CarbonAware.LocationSources.LocationSource: Warning: New key swedencentral_1 generated from swedencentral
```

## Error Handling

Expand Down
14 changes: 0 additions & 14 deletions src/CarbonAware.WebApi/src/Controllers/CarbonAwareController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,18 +241,4 @@ public async Task<IActionResult> GetAverageCarbonIntensityBatch([FromBody] IEnum
return Ok(result);
}
}

/// <summary>
/// Get all locations
/// </summary>
/// <returns>Dictionary with the locations</returns>
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IDictionary<string, Location>))]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[HttpGet("locations")]
public async Task<IActionResult> GetAllLocations()
{
var response = await _locationSource.GetGeopositionLocationsAsync();
return response.Any() ? Ok(response) : NoContent();
}
}
35 changes: 35 additions & 0 deletions src/CarbonAware.WebApi/src/Controllers/LocationsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using CarbonAware.Interfaces;
using CarbonAware.Model;
using Microsoft.AspNetCore.Mvc;

namespace CarbonAware.WebApi.Controllers;

[ApiController]
[Route("locations")]
public class LocationsController : ControllerBase
{
private readonly ILogger<CarbonAwareController> _logger;

private readonly ILocationSource _locationSource;


public LocationsController(ILogger<CarbonAwareController> logger, ILocationSource locationSouce)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_locationSource = locationSouce ?? throw new ArgumentNullException(nameof(locationSouce));
}

/// <summary>
/// Get all locations instances
/// </summary>
/// <returns>Dictionary with <see cref="Location"/> instances</returns>
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IDictionary<string, Location>))]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[HttpGet()]
public async Task<IActionResult> GetAllLocations()
{
var response = await _locationSource.GetGeopositionLocationsAsync();
return response.Any() ? Ok(response) : NoContent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class CarbonAwareControllerTests : IntegrationTestingBase
private readonly string batchForecastURI = "/emissions/forecasts/batch";
private readonly string averageCarbonIntensityURI = "/emissions/average-carbon-intensity";
private readonly string batchAverageCarbonIntensityURI = "/emissions/average-carbon-intensity/batch";
private readonly string locationsURI = "/emissions/locations";


public CarbonAwareControllerTests(DataSourceType dataSource) : base(dataSource) { }

Expand Down Expand Up @@ -306,21 +306,6 @@ public async Task EmissionsMarginalCarbonIntensityBatch_SupportedDataSources_Ret
}
}

[Test]
public async Task GetLocations_ReturnsOk()
{
var result = await _client.GetAsync(locationsURI);
Assert.That(result, Is.Not.Null);
Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.OK));
Assert.That(result.Content, Is.Not.Null);
using var stream = await result.Content.ReadAsStreamAsync();
Assert.That(stream, Is.Not.Null);
var data = await JsonSerializer.DeserializeAsync<IDictionary<string, dynamic>>(stream);
Assert.That(data, Is.Not.Null);
Assert.That(data!.ContainsKey("eastus"), Is.True);
Assert.That(data!.ContainsKey("northeurope"), Is.True);
}

private void IgnoreTestForDataSource(string reasonMessage, params DataSourceType[] ignoredDataSources)
{
if (ignoredDataSources.Contains(_dataSource))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using CarbonAware.DataSources.Configuration;
using CarbonAware.WebApi.IntegrationTests;
using NUnit.Framework;
using System.Net;
using System.Text.Json;

namespace CarbonAware.WepApi.IntegrationTests;

/// <summary>
/// Tests that the Web API controller handles locations instances
/// </summary>
[TestFixture(DataSourceType.JSON)]
[TestFixture(DataSourceType.WattTime)]
[TestFixture(DataSourceType.ElectricityMaps)]
public class LocationsControllerTests : IntegrationTestingBase
{
private readonly string locationsURI = "/locations";

public LocationsControllerTests(DataSourceType dataSource) : base(dataSource) { }


[Test]
public async Task GetLocations_ReturnsOk()
{
var result = await _client.GetAsync(locationsURI);
Assert.That(result, Is.Not.Null);
Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.OK));
Assert.That(result.Content, Is.Not.Null);
using var stream = await result.Content.ReadAsStreamAsync();
Assert.That(stream, Is.Not.Null);
var data = await JsonSerializer.DeserializeAsync<IDictionary<string, dynamic>>(stream);
Assert.That(data, Is.Not.Null);
Assert.That(data!.ContainsKey("eastus"), Is.True);
Assert.That(data!.ContainsKey("northeurope"), Is.True);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,32 +238,4 @@ public void GetEmissionsDataForLocationsByTime_NoLocations_ThrowsException(param

Assert.ThrowsAsync<ArgumentException>(async () => await controller.GetEmissionsDataForLocationsByTime(parametersDTO));
}

/// <summary>
/// Test result with content
/// </summary>
[Test]
public async Task GetLocations_ResultsOk()
{
var controller = new CarbonAwareController(this.MockCarbonAwareLogger.Object, CreateEmissionsAggregator(new List<EmissionsData>()).Object, forecastAggregator, CreateLocations().Object);

IActionResult result = await controller.GetAllLocations();

//Assert
TestHelpers.AssertStatusCode(result, HttpStatusCode.OK);
}

/// <summary>
/// Test result without content
/// </summary>
[Test]
public async Task GetLocations_ResultsNoContent()
{
var controller = new CarbonAwareController(this.MockCarbonAwareLogger.Object, CreateEmissionsAggregator(new List<EmissionsData>()).Object, forecastAggregator, CreateLocations(false).Object);

IActionResult result = await controller.GetAllLocations();

//Assert
TestHelpers.AssertStatusCode(result, HttpStatusCode.NoContent);
}
}
41 changes: 41 additions & 0 deletions src/CarbonAware.WebApi/test/unitTests/LocationsControllerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using CarbonAware.WebApi.Controllers;
using Microsoft.AspNetCore.Mvc;
using NUnit.Framework;
using System.Net;

namespace CarbonAware.WepApi.UnitTests;

/// <summary>
/// Tests that the Web API controller handles request for Location instances
/// </summary>
[TestFixture]
public class LocationsControllerTests : TestsBase
{
/// <summary>
/// Test result with content
/// </summary>
[Test]
public async Task GetLocations_ResultsOk()
{
var controller = new LocationsController(this.MockCarbonAwareLogger.Object, CreateLocations().Object);

IActionResult result = await controller.GetAllLocations();

//Assert
TestHelpers.AssertStatusCode(result, HttpStatusCode.OK);
}

/// <summary>
/// Test result without content
/// </summary>
[Test]
public async Task GetLocations_ResultsNoContent()
{
var controller = new LocationsController(this.MockCarbonAwareLogger.Object, CreateLocations(false).Object);

IActionResult result = await controller.GetAllLocations();

//Assert
TestHelpers.AssertStatusCode(result, HttpStatusCode.NoContent);
}
}

0 comments on commit 0942c07

Please sign in to comment.