Skip to content

Commit

Permalink
feat: revamp application list with grouping support (#905)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmoysrt authored Jul 18, 2024
1 parent 7371bf4 commit 8796737
Show file tree
Hide file tree
Showing 16 changed files with 343 additions and 158 deletions.
128 changes: 6 additions & 122 deletions container_manager/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,140 +255,24 @@ func (m Manager) SetServiceReplicaCount(serviceName string, replicas int) error
}
}

func (m Manager) RealtimeInfoRunningServices() (map[string]ServiceRealtimeInfo, error) {
// fetch all nodes and store in map > nodeID:nodeDetails
nodes, err := m.client.NodeList(m.ctx, types.NodeListOptions{})
if err != nil {
return nil, errors.New("error getting node list")
}
nodeMap := make(map[string]swarm.Node)
for _, node := range nodes {
nodeMap[node.ID] = node
}
// fetch all services and store in map > serviceName:serviceDetails
services, err := m.client.ServiceList(m.ctx, types.ServiceListOptions{})
if err != nil {
return nil, errors.New("error getting service list")
}
// create map of service name to service realtime info
serviceRealtimeInfoMap := make(map[string]ServiceRealtimeInfo)
// analyze each service
for _, service := range services {
runningCount := 0

// inspect service to get desired count
serviceData, _, err := m.client.ServiceInspectWithRaw(m.ctx, service.ID, types.ServiceInspectOptions{})
if err != nil {
continue
}
// create service realtime info
serviceRealtimeInfo := ServiceRealtimeInfo{}
serviceRealtimeInfo.Name = serviceData.Spec.Name
serviceRealtimeInfo.PlacementInfos = []ServiceTaskPlacementInfo{}
// set desired count
if serviceData.Spec.Mode.Replicated != nil {
serviceRealtimeInfo.DesiredReplicas = int(*serviceData.Spec.Mode.Replicated.Replicas)
serviceRealtimeInfo.ReplicatedService = true
} else {
serviceRealtimeInfo.DesiredReplicas = -1
serviceRealtimeInfo.ReplicatedService = false
}

// query task list
tasks, err := m.client.TaskList(m.ctx, types.TaskListOptions{
Filters: filters.NewArgs(
filters.Arg("service", serviceData.Spec.Name),
),
})
if err != nil {
continue
}
servicePlacementCountMap := make(map[string]int) // nodeID:count
// set placement infos > how many replicas are running in each node
for _, task := range tasks {
if task.Status.State == swarm.TaskStateRunning {
servicePlacementCountMap[task.NodeID]++
}
}
for nodeID, count := range servicePlacementCountMap {
node := nodeMap[nodeID]
serviceRealtimeInfo.PlacementInfos = append(serviceRealtimeInfo.PlacementInfos, ServiceTaskPlacementInfo{
NodeID: nodeID,
NodeName: node.Description.Hostname,
IsManagerNode: node.Spec.Role != swarm.NodeRoleManager,
RunningReplicas: count,
})
runningCount += count
}
// set service realtime info in map
serviceRealtimeInfo.RunningReplicas = runningCount
serviceRealtimeInfoMap[serviceRealtimeInfo.Name] = serviceRealtimeInfo
}
return serviceRealtimeInfoMap, nil
}

func (m Manager) RealtimeInfoService(serviceName string, ignoreNodeDetails bool) (ServiceRealtimeInfo, error) {
runningCount := 0
serviceRealtimeInfo := ServiceRealtimeInfo{}
// fetch all nodes and store in map > nodeID:nodeDetails
nodeMap := make(map[string]swarm.Node)
if !ignoreNodeDetails {
nodes, err := m.client.NodeList(m.ctx, types.NodeListOptions{})
if err != nil {
return serviceRealtimeInfo, errors.New("error getting node list")
}
for _, node := range nodes {
nodeMap[node.ID] = node
}
}
// inspect service to get desired count
serviceData, _, err := m.client.ServiceInspectWithRaw(m.ctx, serviceName, types.ServiceInspectOptions{})
if err != nil {
return serviceRealtimeInfo, errors.New("error getting service")
}
// create service realtime info
serviceRealtimeInfo.Name = serviceData.Spec.Name
serviceRealtimeInfo.PlacementInfos = []ServiceTaskPlacementInfo{}
// set desired count
if serviceData.Spec.Mode.Replicated != nil {
serviceRealtimeInfo.DesiredReplicas = int(*serviceData.Spec.Mode.Replicated.Replicas)
serviceRealtimeInfo.ReplicatedService = true
} else {
serviceRealtimeInfo.DesiredReplicas = -1
serviceRealtimeInfo.ReplicatedService = false
}

func (m Manager) NoOfRunningTasks(serviceName string) (int, error) {
// query task list
tasks, err := m.client.TaskList(m.ctx, types.TaskListOptions{
Filters: filters.NewArgs(
filters.Arg("service", serviceData.Spec.Name),
filters.Arg("service", serviceName),
),
})
if err != nil {
return serviceRealtimeInfo, err
return 0, err
}
servicePlacementCountMap := make(map[string]int) // nodeID:count
runningCount := 0
// set placement infos > how many replicas are running in each node
for _, task := range tasks {
if task.Status.State == swarm.TaskStateRunning {
servicePlacementCountMap[task.NodeID]++
}
}
for nodeID, count := range servicePlacementCountMap {
if !ignoreNodeDetails {
node := nodeMap[nodeID]
serviceRealtimeInfo.PlacementInfos = append(serviceRealtimeInfo.PlacementInfos, ServiceTaskPlacementInfo{
NodeID: nodeID,
NodeName: node.Description.Hostname,
IsManagerNode: node.Spec.Role != swarm.NodeRoleManager,
RunningReplicas: count,
})
runningCount++
}
runningCount += count
}
// set service realtime info in map
serviceRealtimeInfo.RunningReplicas = runningCount
return serviceRealtimeInfo, nil
return runningCount, nil
}

// ServiceRunningServers Fetch the servers where a service is running
Expand Down
9 changes: 4 additions & 5 deletions container_manager/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ type CustomHealthCheck struct {
}

type ServiceRealtimeInfo struct {
Name string `json:"name"`
PlacementInfos []ServiceTaskPlacementInfo `json:"placementinfos"`
DesiredReplicas int `json:"desiredreplicas"`
RunningReplicas int `json:"runningreplicas"`
ReplicatedService bool `json:"replicatedservice"`
Name string `json:"name"`
DesiredReplicas int `json:"desiredreplicas"`
RunningReplicas int `json:"runningreplicas"`
ReplicatedService bool `json:"replicatedservice"`
}

type ServiceTaskPlacementInfo struct {
Expand Down
9 changes: 7 additions & 2 deletions swiftwave_service/core/application.operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,14 @@ func IsExistApplicationName(_ context.Context, db gorm.DB, dockerManager contain
return false, nil
}

func FindAllApplications(_ context.Context, db gorm.DB) ([]*Application, error) {
func FindAllApplications(_ context.Context, db gorm.DB, includeGroupedApplications bool) ([]*Application, error) {
var applications []*Application
tx := db.Find(&applications)
var tx *gorm.DB
if includeGroupedApplications {
tx = db.Find(&applications)
} else {
tx = db.Where("application_group_id IS NULL").Find(&applications)
}
return applications, tx.Error
}

Expand Down
6 changes: 4 additions & 2 deletions swiftwave_service/core/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,12 @@ type ConfigMount struct {
FileMode uint `json:"file_mode" gorm:"default:444"`
}

// ApplicationGroup hold information about application group
// ApplicationGroup hold information about application-group
type ApplicationGroup struct {
ID string `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"unique"`
Name string `json:"name"`
Logo string `json:"logo"`
StackContent string `json:"stack_content"`
Applications []Application `json:"applications" gorm:"foreignKey:ApplicationGroupID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- reverse: modify "application_groups" table
ALTER TABLE "public"."application_groups" DROP COLUMN "stack_content", DROP COLUMN "logo", ADD CONSTRAINT "uni_application_groups_name" UNIQUE ("name");
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- modify "application_groups" table
ALTER TABLE "public"."application_groups" DROP CONSTRAINT "uni_application_groups_name", ADD COLUMN "logo" text NULL, ADD COLUMN "stack_content" text NULL;
4 changes: 3 additions & 1 deletion swiftwave_service/db/migrations/atlas.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
h1:hvxXPYu5/HahR/1ICKIZo/MYqsNXMabxSt0SdHKNf8Q=
h1:k1qJKQt8Sk2nl3wA2bU97eDfUN6gf5sarKNVQ0Ez5Lw=
20240413191732_init.down.sql h1:HoitObGwuKF/akF4qg3dol2FfNTLCEuf6wHYDuCez8I=
20240413191732_init.up.sql h1:USKdQx/yTz1KJ0+mDwYGhKm3WzX7k+I9+6B6SxImwaE=
20240414051823_server_custom_ssh_port_added.down.sql h1:IC1DFQBQceTPTRdZOo5/WqytH+ZbgcKrQuMCkhArF/0=
Expand Down Expand Up @@ -43,3 +43,5 @@ h1:hvxXPYu5/HahR/1ICKIZo/MYqsNXMabxSt0SdHKNf8Q=
20240625161343_rename_app_status_live_to_deployed.up.sql h1:J5B2Il4UoFg9fZtj1tkCXIJoDHhCDYjj1XUA2088JRc=
20240626072036_move_application_group_to_relation.down.sql h1:oMF4rB5As6BFCMPAxbm7lXvWyyCb9uqmFOC/AcTsDY8=
20240626072036_move_application_group_to_relation.up.sql h1:SNdKqmYmIZeE0JcgKiLYFajW/awiz4rXRSAKVdabPZg=
20240628175617_add_extra_fields_in_app_group.down.sql h1:T/QBEilqWYysok6l2wxZAlYK1Z6ceSQLUmers5fZNig=
20240628175617_add_extra_fields_in_app_group.up.sql h1:+qBOQc/2bhG1igFdUbWSsZEy01aORuPyBPvxKVXJJoA=
4 changes: 4 additions & 0 deletions swiftwave_service/gqlgen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ models:
resolver: true
applicationGroup:
resolver: true
RealtimeInfo:
fields:
HealthStatus:
resolver: true
ApplicationGroup:
fields:
applications:
Expand Down
49 changes: 37 additions & 12 deletions swiftwave_service/graphql/application.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions swiftwave_service/graphql/application_group.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8796737

Please sign in to comment.