Skip to content

Commit 222c87a

Browse files
author
agile.zhou
committed
Merge branch 'master' into publish
2 parents 49d6820 + 0648075 commit 222c87a

71 files changed

Lines changed: 6025 additions & 512 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
[Dd]ebugPublic/
1616
[Rr]elease/
1717
[Rr]eleases/
18+
!src/AgileConfig.Server.Application/Releases/
19+
!src/AgileConfig.Server.Application/Releases/**
1820
x64/
1921
x86/
2022
bld/

AgileConfig.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.Event",
5656
EndProject
5757
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.EventHandler", "src\AgileConfig.Server.EventHandler\AgileConfig.Server.EventHandler.csproj", "{899F5AAE-2C6F-4F0A-9358-6F5C7D0412DC}"
5858
EndProject
59+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.Application", "src\AgileConfig.Server.Application\AgileConfig.Server.Application.csproj", "{CA724F53-FA58-44CC-B0E7-5FD05CF5E63E}"
60+
EndProject
61+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AgileConfig.Server.ApplicationTests", "test\AgileConfig.Server.ApplicationTests\AgileConfig.Server.ApplicationTests.csproj", "{0AF33559-2F97-4F77-B8E4-859B6A341BA8}"
62+
EndProject
5963
Global
6064
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6165
Debug|Any CPU = Debug|Any CPU
@@ -142,6 +146,14 @@ Global
142146
{899F5AAE-2C6F-4F0A-9358-6F5C7D0412DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
143147
{899F5AAE-2C6F-4F0A-9358-6F5C7D0412DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
144148
{899F5AAE-2C6F-4F0A-9358-6F5C7D0412DC}.Release|Any CPU.Build.0 = Release|Any CPU
149+
{CA724F53-FA58-44CC-B0E7-5FD05CF5E63E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
150+
{CA724F53-FA58-44CC-B0E7-5FD05CF5E63E}.Debug|Any CPU.Build.0 = Debug|Any CPU
151+
{CA724F53-FA58-44CC-B0E7-5FD05CF5E63E}.Release|Any CPU.ActiveCfg = Release|Any CPU
152+
{CA724F53-FA58-44CC-B0E7-5FD05CF5E63E}.Release|Any CPU.Build.0 = Release|Any CPU
153+
{0AF33559-2F97-4F77-B8E4-859B6A341BA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
154+
{0AF33559-2F97-4F77-B8E4-859B6A341BA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
155+
{0AF33559-2F97-4F77-B8E4-859B6A341BA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
156+
{0AF33559-2F97-4F77-B8E4-859B6A341BA8}.Release|Any CPU.Build.0 = Release|Any CPU
145157
EndGlobalSection
146158
GlobalSection(SolutionProperties) = preSolution
147159
HideSolutionNode = FALSE
@@ -167,6 +179,8 @@ Global
167179
{AC7E4D24-D5E8-4E30-BFB0-5DDC581CB0C2} = {F277EC27-8C0E-4490-9645-F5F3244F9246}
168180
{C1138EE0-0C28-4BDE-82CD-CCE621C21BD0} = {1D2FD643-CB85-40F9-BC8A-CE4A39E9F43E}
169181
{899F5AAE-2C6F-4F0A-9358-6F5C7D0412DC} = {1D2FD643-CB85-40F9-BC8A-CE4A39E9F43E}
182+
{CA724F53-FA58-44CC-B0E7-5FD05CF5E63E} = {1D2FD643-CB85-40F9-BC8A-CE4A39E9F43E}
183+
{0AF33559-2F97-4F77-B8E4-859B6A341BA8} = {F277EC27-8C0E-4490-9645-F5F3244F9246}
170184
EndGlobalSection
171185
GlobalSection(ExtensibilityGlobals) = postSolution
172186
SolutionGuid = {7F10DB58-5B6F-4EAC-994F-14E8046B306F}

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
![Docker image](https://img.shields.io/docker/v/kklldog/agile_config?label=docker%20image)
1414
![GitHub license](https://img.shields.io/github/license/dotnetcore/AgileConfig)
1515
![build workflow](https://github.com/dotnetcore/AgileConfig/actions/workflows/master-ci.yml/badge.svg)
16+
[![Unit test coverage](https://img.shields.io/badge/unit%20test%20coverage-60%25-brightgreen)](https://github.com/dotnetcore/AgileConfig/pull/254)
1617
[![package workflow](https://github.com/dotnetcore/AgileConfig/actions/workflows/release-xxx.yml/badge.svg)](https://github.com/dotnetcore/AgileConfig/actions/workflows/release-xxx.yml)
1718
![Commit Date](https://img.shields.io/github/last-commit/dotnetcore/AgileConfig/master.svg?logo=github&logoColor=green&label=commit)
1819

@@ -47,7 +48,8 @@ GO Client:[agileconfig_client_go](https://github.com/kklldog/agileconfig_clien
4748
Python Client:[agileconfig_client_python](https://github.com/kklldog/agileconfig_client_python)
4849
GO Client:[go-agile-config](https://github.com/animacaeli/go-agile-config)
4950
Python Client:[py-agile-config](https://github.com/animacaeli/py-agile-config)
50-
Nodejs Client: [node-agile-client](https://github.com/LetTTGACO/node-agile-client)
51+
Nodejs Client: [node-agile-client](https://github.com/LetTTGACO/node-agile-client)
52+
Rust Client: [agile-config-client](https://crates.io/crates/agile-config-client)
5153
Blazor UI:[AgileConfigBlazorUI](https://github.com/EzrealJ/AgileConfigBlazorUI)
5254

5355
samples :

README_CN.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ JAVA 客户端项目:[AgileConfig_JClient](https://github.com/kklldog/agilecon
3939
GO 客户端项目:[AgileConfig_GoClient](https://github.com/kklldog/agileconfig_client_go)
4040
Python 客户端项目:[AgileConfig_GoClient](https://github.com/kklldog/agileconfig_client_python)
4141
GO 客户端项目:[go-agile-config](https://github.com/animacaeli/go-agile-config)
42-
Python 客户端项目:[py-agile-config](https://github.com/animacaeli/py-agile-config)
42+
Python 客户端项目:[py-agile-config](https://github.com/animacaeli/py-agile-config)
4343
Nodejs 实现的客户端: [node-agile-client](https://github.com/LetTTGACO/node-agile-client)
44+
Rust 实现的客户端: [agile-config-client](https://crates.io/crates/agile-config-client)
4445
Blazor 实现的管理界面:[AgileConfigBlazorUI](https://github.com/EzrealJ/AgileConfigBlazorUI)
4546

4647
示例项目:

README_EN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Python Client:[AgileConfig_GoClient](https://github.com/kklldog/agileconfig_cl
4747
GO Client:[go-agile-config](https://github.com/animacaeli/go-agile-config)
4848
Python Client:[py-agile-config](https://github.com/animacaeli/py-agile-config)
4949
Nodejs Client: [node-agile-client](https://github.com/LetTTGACO/node-agile-client)
50+
Rust Client: [agile-config-client](https://crates.io/crates/agile-config-client)
5051
Blazor UI:[AgileConfigBlazorUI](https://github.com/EzrealJ/AgileConfigBlazorUI)
5152

5253
samples :

coverlet.runsettings

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RunSettings>
3+
<DataCollectionRunSettings>
4+
<DataCollectors>
5+
<DataCollector friendlyName="XPlat code coverage">
6+
<Configuration>
7+
<Format>cobertura</Format>
8+
<Exclude>[*.Tests]*,[Agile.Config.Protocol]*,[AgileConfig.Server.Event]*,[AgileConfig.Server.IService]*</Exclude>
9+
<ExcludeByAttribute>System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute,GeneratedCodeAttribute</ExcludeByAttribute>
10+
<ExcludeByFile>**/obj/**/*.cs,**/AgileConfig.Server.Data.Entity/App.cs,**/AgileConfig.Server.Data.Entity/AppInheritanced.cs,**/AgileConfig.Server.Data.Entity/Config.cs,**/AgileConfig.Server.Data.Entity/Function.cs,**/AgileConfig.Server.Data.Entity/PublishDetail.cs,**/AgileConfig.Server.Data.Entity/PublishTimeline.cs,**/AgileConfig.Server.Data.Entity/Role.cs,**/AgileConfig.Server.Data.Entity/RoleFunction.cs,**/AgileConfig.Server.Data.Entity/ServerNode.cs,**/AgileConfig.Server.Data.Entity/ServiceInfo.cs,**/AgileConfig.Server.Data.Entity/Setting.cs,**/AgileConfig.Server.Data.Entity/User.cs,**/AgileConfig.Server.Data.Entity/UserAppAuth.cs,**/AgileConfig.Server.Data.Entity/UserRole.cs,**/AppExportVM.cs,**/ApiPublishTimelineVM.cs,**/ApiServiceInfoVM.cs,**/HeartbeatParam.cs,**/HeartbeatResultVM.cs,**/RegisterResultVM.cs,**/ApplicationModels.cs,**/ConfigurationModels.cs,**/NodeModels.cs,**/ReleaseModels.cs,**/ApplicationManagement.cs,**/ConfigurationManagementContracts.cs,**/NodeManagementModels.cs,**/ReleaseManagementContracts.cs,**/ServiceInstanceManagementModels.cs,**/DbConfigInfo.cs,**/OidcSetting.cs,**/UIFileBag.cs,**/IWebsocketCollection.cs,**/Appsettings.cs,**/SystemSettings.cs,**/Global.cs</ExcludeByFile>
11+
</Configuration>
12+
</DataCollector>
13+
</DataCollectors>
14+
</DataCollectionRunSettings>
15+
</RunSettings>

docs/api-v2.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# AgileConfig REST API v2
2+
3+
API v2 is available below `/api/v2`. It is additive: the existing `/api/*` endpoints remain available and keep
4+
their original contracts.
5+
6+
## Authentication
7+
8+
- Administrative resources use HTTP Basic authentication with an AgileConfig administrator username and password.
9+
- `published-configurations` uses the application ID and secret as the Basic authentication username and password.
10+
- Service registration and heartbeat endpoints remain unauthenticated for compatibility with the existing service
11+
registry protocol. Service instance queries and deletion require administrator Basic authentication.
12+
13+
Administrative actions continue to enforce the same AgileConfig function permissions as their v1 equivalents.
14+
15+
## Resources
16+
17+
| Method | Path | Result |
18+
| --- | --- | --- |
19+
| `GET` | `/api/v2/applications` | List applications |
20+
| `POST` | `/api/v2/applications` | Create an application |
21+
| `GET` | `/api/v2/applications/{applicationId}` | Get an application |
22+
| `PUT` | `/api/v2/applications/{applicationId}` | Replace an application |
23+
| `DELETE` | `/api/v2/applications/{applicationId}` | Delete an application |
24+
| `GET` | `/api/v2/applications/{applicationId}/environments/{environment}/configurations` | List editable configurations |
25+
| `POST` | `/api/v2/applications/{applicationId}/environments/{environment}/configurations` | Create a configuration |
26+
| `GET` | `/api/v2/applications/{applicationId}/environments/{environment}/configurations/{configurationId}` | Get a configuration |
27+
| `PUT` | `/api/v2/applications/{applicationId}/environments/{environment}/configurations/{configurationId}` | Replace a configuration |
28+
| `DELETE` | `/api/v2/applications/{applicationId}/environments/{environment}/configurations/{configurationId}` | Mark a configuration for deletion |
29+
| `GET` | `/api/v2/applications/{applicationId}/environments/{environment}/published-configurations` | Pull the effective published configuration |
30+
| `GET` | `/api/v2/applications/{applicationId}/environments/{environment}/releases` | List releases |
31+
| `POST` | `/api/v2/applications/{applicationId}/environments/{environment}/releases` | Publish pending changes |
32+
| `GET` | `/api/v2/applications/{applicationId}/environments/{environment}/releases/{releaseId}` | Get a release |
33+
| `POST` | `/api/v2/applications/{applicationId}/environments/{environment}/releases/rollbacks` | Roll back to a release |
34+
| `GET` | `/api/v2/nodes` | List cluster nodes |
35+
| `POST` | `/api/v2/nodes` | Add a cluster node |
36+
| `GET` | `/api/v2/nodes/{nodeId}` | Get a cluster node |
37+
| `DELETE` | `/api/v2/nodes/{nodeId}` | Delete a cluster node |
38+
| `GET` | `/api/v2/service-instances?status={Healthy\|Unhealthy}` | List or filter service instances |
39+
| `POST` | `/api/v2/service-instances` | Register or refresh a service instance |
40+
| `GET` | `/api/v2/service-instances/{serviceInstanceId}` | Get a service instance |
41+
| `DELETE` | `/api/v2/service-instances/{serviceInstanceId}` | Unregister a service instance |
42+
| `PUT` | `/api/v2/service-instances/{serviceInstanceId}/heartbeat` | Record a heartbeat |
43+
44+
Node IDs are opaque URL-safe values returned by the API. Clients should not construct them from node addresses.
45+
46+
## HTTP semantics
47+
48+
- Creation returns `201 Created`, the created representation, and a `Location` header. Re-registering an existing
49+
service instance returns `200 OK` because the existing resource is updated.
50+
- Successful deletion and rollback return `204 No Content`.
51+
- Missing resources return `404 Not Found`; identifier/key conflicts return `409 Conflict`.
52+
- Validation and domain errors use `application/problem+json` (`ProblemDetails`). Authentication and permission
53+
failures retain the server's existing `403 Forbidden` behavior.
54+
- Published configuration responses include `ETag` and `X-Publish-Timeline-Id`. Sending the ETag in
55+
`If-None-Match` returns `304 Not Modified` when the published version has not changed.
56+
57+
Deleting an already published configuration removes it from the v2 editable resource view immediately, while the
58+
previous published value remains available to application clients until the pending deletion is released.

docs/application-layer.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Application layer
2+
3+
`AgileConfig.Server.Application` contains transport-independent application use cases. Both the legacy MVC controllers and the REST API controllers call this layer so that business behavior is implemented once.
4+
5+
## Dependency direction
6+
7+
```text
8+
Apisite controllers
9+
|
10+
v
11+
AgileConfig.Server.Application
12+
|
13+
v
14+
AgileConfig.Server.IService / domain events
15+
|
16+
v
17+
repositories
18+
```
19+
20+
The Application project must not reference ASP.NET Core MVC, Apisite request models, controllers, or HTTP result types.
21+
22+
## Responsibilities
23+
24+
Controllers own:
25+
26+
- authentication and authorization filters;
27+
- HTTP request and response models;
28+
- status codes, headers, routes, and `ProblemDetails`;
29+
- compatibility mapping for legacy response envelopes.
30+
31+
Application services own:
32+
33+
- use-case validation and conflict detection;
34+
- entity creation and state transitions;
35+
- orchestration of the existing business services;
36+
- current-user audit values and timestamps;
37+
- domain-event publication and other required side effects.
38+
39+
The existing services in `AgileConfig.Server.IService` and `AgileConfig.Server.Service` continue to own persistence-oriented operations, queries, caches, and lower-level domain behavior.
40+
41+
Expected business failures are returned as `ApplicationResult` values. Application services do not return `IActionResult`, select HTTP status codes, or format user-facing HTTP payloads.
42+
43+
## Compatibility
44+
45+
Legacy and v2 controllers deliberately map the same application result differently:
46+
47+
- legacy controllers preserve their existing `{ success, message, data }` envelopes and status-code behavior;
48+
- v2 controllers use resource responses, standard status codes, and `ProblemDetails`.
49+
50+
Any application-service migration must keep integration coverage for both contracts.

src/AgileConfig.Server.Apisite/AgileConfig.Server.Apisite.csproj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<PropertyGroup>
44
<TargetFramework>net10.0</TargetFramework>
55
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
6-
<AssemblyVersion>1.13.1</AssemblyVersion>
7-
<Version>1.13.1</Version>
8-
<PackageVersion>1.13.1</PackageVersion>
6+
<AssemblyVersion>1.13.2</AssemblyVersion>
7+
<Version>1.13.2</Version>
8+
<PackageVersion>1.13.2</PackageVersion>
99
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
10-
<FileVersion>1.13.1</FileVersion>
10+
<FileVersion>1.13.2</FileVersion>
1111
<Authors>kklldog</Authors>
1212
<Company>kklldog</Company>
1313
</PropertyGroup>
@@ -48,6 +48,7 @@
4848
</ItemGroup>
4949

5050
<ItemGroup>
51+
<ProjectReference Include="..\AgileConfig.Server.Application\AgileConfig.Server.Application.csproj" />
5152
<ProjectReference Include="..\AgileConfig.Server.Common\AgileConfig.Server.Common.csproj" />
5253
<ProjectReference Include="..\AgileConfig.Server.Data.Abstraction\AgileConfig.Server.Data.Abstraction.csproj" />
5354
<ProjectReference Include="..\AgileConfig.Server.Data.Repository.Freesql\AgileConfig.Server.Data.Repository.Freesql.csproj" />
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using AgileConfig.Server.Application;
2+
using AgileConfig.Server.Common;
3+
4+
namespace AgileConfig.Server.Apisite.Application;
5+
6+
public sealed class AppsettingsPreviewModeAccessor : IPreviewModeAccessor
7+
{
8+
public bool IsPreviewMode => Appsettings.IsPreviewMode;
9+
}

0 commit comments

Comments
 (0)