Skip to content
This repository has been archived by the owner on Nov 24, 2022. It is now read-only.

fix(swarm): add an extra wait of 5 seconds to consider a service up #25

Merged
merged 2 commits into from
Apr 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
npm i -G semantic-release @semantic-release/exec
npx semantic-release -b main
npx semantic-release
42 changes: 41 additions & 1 deletion pkg/scaler/docker_swarm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package scaler
import (
"context"
"fmt"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
Expand Down Expand Up @@ -84,7 +85,46 @@ func (scaler *DockerSwarmScaler) IsUp(name string) bool {
return false
}

return service.ServiceStatus.DesiredTasks > 0 && (service.ServiceStatus.DesiredTasks == service.ServiceStatus.RunningTasks)
return scaler.isServiceRunningFor(service, 5*time.Second)
}

func (scaler *DockerSwarmScaler) isServiceRunningFor(service *swarm.Service, duration time.Duration) bool {

if service.ServiceStatus.DesiredTasks == 0 {
return false
}

if service.ServiceStatus.DesiredTasks != service.ServiceStatus.RunningTasks {
return false
}

opts := types.TaskListOptions{
Filters: filters.NewArgs(),
}
opts.Filters.Add("desired-state", "running")
opts.Filters.Add("service", service.Spec.Name)

ctx := context.Background()
tasks, err := scaler.Client.TaskList(ctx, opts)
if err != nil {
log.Error(err.Error())
return false
}

if len(tasks) == 0 {
log.Error("No task found with filter desired-state=running and service=", service.Spec.Name)
return false
}

// Getting 503 first time a workload is woken up https://github.com/acouvreur/traefik-ondemand-service/issues/24
// Let the service be up for a given duration
for _, task := range tasks {
if time.Since(task.Status.Timestamp) < (time.Second * 5) {
return false
}
}

return true
}

func (scaler *DockerSwarmScaler) GetServiceByName(name string, ctx context.Context) (*swarm.Service, error) {
Expand Down
49 changes: 47 additions & 2 deletions pkg/scaler/docker_swarm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"reflect"
"testing"
"time"

"github.com/acouvreur/traefik-ondemand-service/pkg/scaler/mocks"
"github.com/docker/docker/api/types"
Expand Down Expand Up @@ -161,6 +162,7 @@ func TestDockerSwarmScaler_IsUp(t *testing.T) {
fields fields
args args
serviceList []swarm.Service
taskList []swarm.Task
want bool
}{
{
Expand Down Expand Up @@ -191,7 +193,7 @@ func TestDockerSwarmScaler_IsUp(t *testing.T) {
want: false,
},
{
name: "service nginx is 1/1",
name: "service nginx is 1/1 since 10 seconds",
fields: fields{
Client: mocks.NewServiceAPIClientMock(),
},
Expand All @@ -215,6 +217,13 @@ func TestDockerSwarmScaler_IsUp(t *testing.T) {
},
},
},
taskList: []swarm.Task{
{
Status: swarm.TaskStatus{
Timestamp: time.Now().Add(-10 * time.Second),
},
},
},
want: true,
},
{
Expand Down Expand Up @@ -242,6 +251,41 @@ func TestDockerSwarmScaler_IsUp(t *testing.T) {
},
},
},
taskList: []swarm.Task{},
want: false,
},
{
name: "service nginx is 1/1 since 2 seconds",
fields: fields{
Client: mocks.NewServiceAPIClientMock(),
},
args: args{
name: "nginx",
},
serviceList: []swarm.Service{
{
ID: "nginx_service",
Meta: swarm.Meta{Version: swarm.Version{}},
Spec: swarm.ServiceSpec{
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &zeroreplicas,
},
},
},
ServiceStatus: &swarm.ServiceStatus{
RunningTasks: 0,
DesiredTasks: 1,
},
},
},
taskList: []swarm.Task{
{
Status: swarm.TaskStatus{
Timestamp: time.Now().Add(-2 * time.Second),
},
},
},
want: false,
},
}
Expand All @@ -252,11 +296,12 @@ func TestDockerSwarmScaler_IsUp(t *testing.T) {
}

tt.fields.Client.On("ServiceList", mock.Anything, mock.Anything).Return(tt.serviceList, nil)
tt.fields.Client.On("TaskList", mock.Anything, mock.Anything).Return(tt.taskList, nil)

got := scaler.IsUp(tt.args.name)

assert.EqualValues(t, tt.want, got)
tt.fields.Client.AssertExpectations(t)
//tt.fields.Client.AssertExpectations(t)
})
}
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/scaler/mocks/client_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,8 @@ func (client *ServiceAPIClientMock) ServiceList(ctx context.Context, options typ
args := client.Mock.Called(ctx, options)
return args.Get(0).([]swarm.Service), args.Error(1)
}

func (client *ServiceAPIClientMock) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
args := client.Mock.Called(ctx, options)
return args.Get(0).([]swarm.Task), args.Error(1)
}
5 changes: 4 additions & 1 deletion release.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module.exports = {
"branches": "main",
"branches": [
{ "name": "main" },
{ "name": "beta", "channel": "beta", "prerelease": "beta" },
],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
Expand Down