Skip to content

REST API Server

The CoSky REST API Server is a Spring Boot WebFlux application that exposes the full set of microservice governance capabilities -- configuration management, service discovery and registration, namespace management, statistics, topology, and security -- as reactive HTTP endpoints. It serves as the primary integration surface for the CoSky Dashboard and any external client.

At a Glance

ComponentResponsibilityKey FileSource
Server entry pointSpring Boot application bootstrapRestApiServer.ktcosky-rest-api/.../RestApiServer.kt:23
Config APIConfiguration CRUD, versioning, import/exportConfigController.ktcosky-rest-api/.../ConfigController.kt:54
Service APIService registry, discovery, load balancingServiceController.ktcosky-rest-api/.../ServiceController.kt:40
Namespace APIMulti-tenant namespace managementNamespaceController.ktcosky-rest-api/.../NamespaceController.kt:39
Stat APIService statistics and topologyStatController.ktcosky-rest-api/.../StatController.kt:37
Stat SchedulerDistributed scheduled statistics aggregationStatServiceScheduler.ktcosky-rest-api/.../StatServiceScheduler.kt:33

Server Entry Point

RestApiServer is a standard @SpringBootApplication class. The main function delegates to SpringApplication.run, which auto-configures the WebFlux server, CoSky discovery, Redis connections, and security components.

kotlin
@SpringBootApplication
class RestApiServer

fun main(args: Array<String>) {
    SpringApplication.run(RestApiServer::class.java, *args)
}

Source: cosky-rest-api/.../RestApiServer.kt:23-28

API Endpoints

All endpoints share the /v1 prefix. The following tables group them by domain.

Config Endpoints

MethodPathDescriptionController MethodSource
GET/v1/namespaces/{namespace}/configsList all config IDsgetConfigsConfigController.kt:65
PUT/v1/namespaces/{namespace}/configs/{configId}Create or update a configsetConfigConfigController.kt:168
DELETE/v1/namespaces/{namespace}/configs/{configId}Delete a configremoveConfigConfigController.kt:177
GET/v1/namespaces/{namespace}/configs/{configId}Get config contentgetConfigConfigController.kt:182
PUT/v1/namespaces/{namespace}/configs/{configId}/to/{targetVersion}Rollback to a target versionrollbackConfigController.kt:187
GET/v1/namespaces/{namespace}/configs/{configId}/versionsList config version historygetConfigVersionsConfigController.kt:196
GET/v1/namespaces/{namespace}/configs/{configId}/versions/{version}Get a specific version's datagetConfigHistoryConfigController.kt:204
POST/v1/namespaces/{namespace}/configs (multipart)Import configs from ZIPimportZipConfigController.kt:69
GET/v1/namespaces/{namespace}/configs/exportExport all configs as ZIPexportZipConfigController.kt:150

Service Endpoints

MethodPathDescriptionController MethodSource
GET/v1/namespaces/{namespace}/servicesList all service IDsgetServicesServiceController.kt:47
PUT/v1/namespaces/{namespace}/services/{serviceId}Create a service entrysetServiceServiceController.kt:52
DELETE/v1/namespaces/{namespace}/services/{serviceId}Remove a serviceremoveServiceServiceController.kt:57
GET/v1/namespaces/{namespace}/services/{serviceId}/instancesList instances of a servicegetInstancesServiceController.kt:62
PUT/v1/namespaces/{namespace}/services/{serviceId}/instancesRegister a service instanceregisterServiceController.kt:67
DELETE/v1/namespaces/{namespace}/services/{serviceId}/instances/{instanceId}Deregister a service instancederegisterServiceController.kt:76
PUT/v1/namespaces/{namespace}/services/{serviceId}/instances/{instanceId}/metadataSet instance metadatasetMetadataServiceController.kt:84
GET/v1/namespaces/{namespace}/services/statsGet service statisticsgetServiceStatsServiceController.kt:95
GET/v1/namespaces/{namespace}/services/{serviceId}/lbLoad-balancer choose instancechooseServiceController.kt:100

Namespace Endpoints

MethodPathDescriptionController MethodSource
GET/v1/namespacesList namespaces (role-scoped)getNamespacesNamespaceController.kt:41
GET/v1/namespaces/currentGet current context namespacecurrentNamespaceController.kt:52
PUT/v1/namespaces/current/{namespace}Set current context namespacesetCurrentContextNamespaceNamespaceController.kt:57
PUT/v1/namespaces/{namespace}Create a namespacesetNamespaceNamespaceController.kt:62
DELETE/v1/namespaces/{namespace}Remove a namespaceremoveNamespaceNamespaceController.kt:67

Stat Endpoints

MethodPathDescriptionController MethodSource
GET/v1/namespaces/{namespace}/statAggregate namespace statisticsgetStatStatController.kt:44
GET/v1/namespaces/{namespace}/stat/topologyGet service dependency topologygetTopologyStatController.kt:74

Auth Endpoints

MethodPathDescriptionController MethodSource
POST/v1/authenticate/{username}/loginLogin with passwordloginAuthenticateController.kt:37
POST/v1/authenticate/{username}/refreshRefresh access tokenrefreshAuthenticateController.kt:47

User Endpoints

MethodPathDescriptionController MethodSource
GET/v1/usersList all users with rolesqueryUserController.kt:42
POST/v1/users/{username}Add a new useraddUserUserController.kt:52
DELETE/v1/users/{username}Remove a userremoveUserUserController.kt:62
PATCH/v1/users/{username}/passwordChange passwordchangePwdUserController.kt:47
PATCH/v1/users/{username}/roleBind roles to userbindRoleUserController.kt:57
DELETE/v1/users/{username}/unlockUnlock a locked-out userunlockUserController.kt:67

Role Endpoints

MethodPathDescriptionController MethodSource
GET/v1/rolesList all rolesallRoleRoleController.kt:38
GET/v1/roles/{roleName}/bindGet resource-action bindingsgetResourceBindRoleController.kt:43
PUT/v1/roles/{roleName}Create or update a rolesaveRoleRoleController.kt:52
DELETE/v1/roles/{roleName}Remove a roleremoveRoleRoleController.kt:57

Audit Log Endpoints

MethodPathDescriptionController MethodSource
GET/v1/audit-logQuery audit logsqueryLogAuditLogController.kt:32

Sequence Diagrams

Config CRUD Operation

mermaid
sequenceDiagram
    autonumber
    participant Client
    participant ConfigController
    participant ConfigService
    participant Redis

    Client->>ConfigController: PUT /v1/namespaces/{ns}/configs/{configId}
    ConfigController->>ConfigService: setConfig(namespace, configId, data)
    ConfigService->>Redis: SET config data + version metadata
    Redis-->>ConfigService: OK
    ConfigService-->>ConfigController: true
    ConfigController-->>Client: 200 true

    Client->>ConfigController: GET /v1/namespaces/{ns}/configs/{configId}
    ConfigController->>ConfigService: getConfig(namespace, configId)
    ConfigService->>Redis: GET config data
    Redis-->>ConfigService: Config data
    ConfigService-->>ConfigController: Config
    ConfigController-->>Client: 200 Config

    Client->>ConfigController: PUT /v1/namespaces/{ns}/configs/{configId}/to/{version}
    ConfigController->>ConfigService: rollback(namespace, configId, targetVersion)
    ConfigService->>Redis: GET history + SET current
    Redis-->>ConfigService: OK
    ConfigService-->>ConfigController: true
    ConfigController-->>Client: 200 true

Service Registration via REST

mermaid
sequenceDiagram
    autonumber
    participant Client
    participant ServiceController
    participant ServiceRegistry
    participant Redis

    Client->>ServiceController: PUT /v1/namespaces/{ns}/services/{svcId}/instances
    ServiceController->>ServiceRegistry: register(namespace, ServiceInstance)
    ServiceRegistry->>Redis: HMSET instance + ZADD service index + PEXPIRE TTL
    Redis-->>ServiceRegistry: OK
    ServiceRegistry-->>ServiceController: true
    ServiceController-->>Client: 200 true

    Client->>ServiceController: DELETE /v1/namespaces/{ns}/services/{svcId}/instances/{instId}
    ServiceController->>ServiceRegistry: deregister(namespace, serviceId, instanceId)
    ServiceRegistry->>Redis: ZREM instance from service set
    Redis-->>ServiceRegistry: true
    ServiceRegistry-->>ServiceController: true
    ServiceController-->>Client: 200 true

Architecture

mermaid
flowchart TB
    subgraph api["REST API Server"]
        direction TB
        subgraph c["Controllers"]
            ConfigCtrl["ConfigController"]
            ServiceCtrl["ServiceController"]
            NamespaceCtrl["NamespaceController"]
            StatCtrl["StatController"]
            AuthCtrl["AuthenticateController"]
            UserCtrl["UserController"]
            RoleCtrl["RoleController"]
            AuditCtrl["AuditLogController"]
        end
        subgraph cs["Core Services"]
            ConfigSvc["ConfigService"]
            ServiceReg["ServiceRegistry"]
            ServiceDisc["ServiceDiscovery"]
            ServiceStat["ServiceStatistic"]
            ServiceTopo["ServiceTopology"]
            NSvc["NamespaceService"]
        end
        subgraph infra["Infrastructure"]
            SimbaScheduler["StatServiceScheduler<br>(Simba)"]
            CoSecAuth["CoSec Security"]
        end
    end

    c --> cs
    cs --> Redis[(Redis)]
    SimbaScheduler --> ServiceStat
    SimbaScheduler --> NSvc
    CoSecAuth --> c

StatServiceScheduler

The StatServiceScheduler is a distributed scheduled job powered by Simba (a distributed mutex / leader-election library). It extends AbstractScheduler and implements Spring's SmartLifecycle so that it starts and stops with the application context.

Key behaviors:

  • Mutex-based leader election: Only one instance in the cluster holds the "stat" mutex and performs work.
  • Schedule: Runs with an initial 1-second delay and then every 10 seconds (ScheduleConfig.delay(1s, 10s)).
  • Namespace iteration: On each tick it iterates all namespaces and calls ServiceStatistic.statService() to aggregate service metrics into Redis.
  • Current namespace guard: Ensures the current context namespace is always present in the namespace list.

Source: cosky-rest-api/.../StatServiceScheduler.kt:33-84

Configuration

The REST API server is configured through application.yaml. Key settings:

yaml
cosky:
  security:
    enabled: true                    # Enable/disable security
    audit-log:
      action: write                  # Audit log filter: "write", "read", or "rw"
    enforce-init-super-user: false   # Force re-initialize super user on startup

cosec:
  jwt:
    algorithm: hmac256               # JWT signing algorithm
    secret: ${cosky.security.key}    # JWT secret key
    token-validity:
      access: 15m                    # Access token TTL
      refresh: 3H                    # Refresh token TTL

cosid:
  namespace: ${spring.application.name}
  machine:
    enabled: true
    distributor:
      type: redis
  generator:
    enabled: true

simba:
  redis:
    enabled: true                    # Enable Simba distributed scheduler via Redis

Source: cosky-rest-api/src/main/resources/application.yaml

References

Released under the Apache License 2.0.