mirror of
https://github.com/sablierapp/sablier.git
synced 2025-12-24 14:31:51 +01:00
This feature adds the capability to stop unregistered running instances upon startup. Previously, you had to stop running instances manually or issue an initial request that will shut down instances afterwards. With this change, all discovered instances will be shutdown. They need to be registered using labels. E.g.: sablier.enable=true Fixes #153
339 lines
8.8 KiB
Go
339 lines
8.8 KiB
Go
package kubernetes
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/acouvreur/sablier/app/instance"
|
|
"github.com/acouvreur/sablier/app/providers/mocks"
|
|
"github.com/stretchr/testify/mock"
|
|
v1 "k8s.io/api/apps/v1"
|
|
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
func TestKubernetesProvider_Start(t *testing.T) {
|
|
type data struct {
|
|
name string
|
|
get *autoscalingv1.Scale
|
|
update *autoscalingv1.Scale
|
|
}
|
|
type args struct {
|
|
name string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want instance.State
|
|
data data
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "scale nginx deployment to 2 replicas",
|
|
args: args{
|
|
name: "deployment_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "deployment_default_nginx_2",
|
|
CurrentReplicas: 0,
|
|
DesiredReplicas: 2,
|
|
Status: instance.NotReady,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
get: mocks.V1Scale(0),
|
|
update: mocks.V1Scale(2),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "scale nginx statefulset to 2 replicas",
|
|
args: args{
|
|
name: "statefulset_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "statefulset_default_nginx_2",
|
|
CurrentReplicas: 0,
|
|
DesiredReplicas: 2,
|
|
Status: instance.NotReady,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
get: mocks.V1Scale(0),
|
|
update: mocks.V1Scale(2),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "scale unsupported kind",
|
|
args: args{
|
|
name: "gateway_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "gateway_default_nginx_2",
|
|
CurrentReplicas: 0,
|
|
DesiredReplicas: 2,
|
|
Status: instance.Unrecoverable,
|
|
Message: "unsupported kind \"gateway\" must be one of \"deployment\", \"statefulset\"",
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
get: mocks.V1Scale(0),
|
|
update: mocks.V1Scale(0),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
deploymentAPI := mocks.DeploymentMock{}
|
|
statefulsetAPI := mocks.StatefulSetsMock{}
|
|
provider := KubernetesProvider{
|
|
Client: mocks.NewKubernetesAPIClientMock(&deploymentAPI, &statefulsetAPI),
|
|
delimiter: "_",
|
|
}
|
|
|
|
deploymentAPI.On("GetScale", mock.Anything, tt.data.name, metav1.GetOptions{}).Return(tt.data.get, nil)
|
|
deploymentAPI.On("UpdateScale", mock.Anything, tt.data.name, tt.data.update, metav1.UpdateOptions{}).Return(nil, nil)
|
|
|
|
statefulsetAPI.On("GetScale", mock.Anything, tt.data.name, metav1.GetOptions{}).Return(tt.data.get, nil)
|
|
statefulsetAPI.On("UpdateScale", mock.Anything, tt.data.name, tt.data.update, metav1.UpdateOptions{}).Return(nil, nil)
|
|
|
|
got, err := provider.Start(context.Background(), tt.args.name)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("KubernetesProvider.Start() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("KubernetesProvider.Start() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestKubernetesProvider_Stop(t *testing.T) {
|
|
type data struct {
|
|
name string
|
|
get *autoscalingv1.Scale
|
|
update *autoscalingv1.Scale
|
|
}
|
|
type args struct {
|
|
name string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want instance.State
|
|
data data
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "scale nginx deployment to 2 replicas",
|
|
args: args{
|
|
name: "deployment_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "deployment_default_nginx_2",
|
|
CurrentReplicas: 0,
|
|
DesiredReplicas: 2,
|
|
Status: instance.NotReady,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
get: mocks.V1Scale(2),
|
|
update: mocks.V1Scale(0),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "scale nginx statefulset to 2 replicas",
|
|
args: args{
|
|
name: "statefulset_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "statefulset_default_nginx_2",
|
|
CurrentReplicas: 0,
|
|
DesiredReplicas: 2,
|
|
Status: instance.NotReady,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
get: mocks.V1Scale(2),
|
|
update: mocks.V1Scale(0),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "scale unsupported kind",
|
|
args: args{
|
|
name: "gateway_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "gateway_default_nginx_2",
|
|
CurrentReplicas: 0,
|
|
DesiredReplicas: 2,
|
|
Status: instance.Unrecoverable,
|
|
Message: "unsupported kind \"gateway\" must be one of \"deployment\", \"statefulset\"",
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
get: mocks.V1Scale(0),
|
|
update: mocks.V1Scale(0),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
deploymentAPI := mocks.DeploymentMock{}
|
|
statefulsetAPI := mocks.StatefulSetsMock{}
|
|
provider := KubernetesProvider{
|
|
Client: mocks.NewKubernetesAPIClientMock(&deploymentAPI, &statefulsetAPI),
|
|
delimiter: "_",
|
|
}
|
|
|
|
deploymentAPI.On("GetScale", mock.Anything, tt.data.name, metav1.GetOptions{}).Return(tt.data.get, nil)
|
|
deploymentAPI.On("UpdateScale", mock.Anything, tt.data.name, tt.data.update, metav1.UpdateOptions{}).Return(nil, nil)
|
|
|
|
statefulsetAPI.On("GetScale", mock.Anything, tt.data.name, metav1.GetOptions{}).Return(tt.data.get, nil)
|
|
statefulsetAPI.On("UpdateScale", mock.Anything, tt.data.name, tt.data.update, metav1.UpdateOptions{}).Return(nil, nil)
|
|
|
|
got, err := provider.Stop(context.Background(), tt.args.name)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("KubernetesProvider.Stop() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("KubernetesProvider.Stop() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestKubernetesProvider_GetState(t *testing.T) {
|
|
type data struct {
|
|
name string
|
|
getDeployment *v1.Deployment
|
|
getStatefulSet *v1.StatefulSet
|
|
}
|
|
type args struct {
|
|
name string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want instance.State
|
|
data data
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "ready nginx deployment with 2 ready replicas",
|
|
args: args{
|
|
name: "deployment_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "deployment_default_nginx_2",
|
|
CurrentReplicas: 2,
|
|
DesiredReplicas: 2,
|
|
Status: instance.Ready,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
getDeployment: mocks.V1Deployment(2, 2),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "not ready nginx deployment with 1 ready replica out of 2",
|
|
args: args{
|
|
name: "deployment_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "deployment_default_nginx_2",
|
|
CurrentReplicas: 1,
|
|
DesiredReplicas: 2,
|
|
Status: instance.NotReady,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
getDeployment: mocks.V1Deployment(2, 1),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "ready nginx statefulset to 2 replicas",
|
|
args: args{
|
|
name: "statefulset_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "statefulset_default_nginx_2",
|
|
CurrentReplicas: 2,
|
|
DesiredReplicas: 2,
|
|
Status: instance.Ready,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
getStatefulSet: mocks.V1StatefulSet(2, 2),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "not ready nginx statefulset to 1 ready replica out of 2",
|
|
args: args{
|
|
name: "statefulset_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "statefulset_default_nginx_2",
|
|
CurrentReplicas: 1,
|
|
DesiredReplicas: 2,
|
|
Status: instance.NotReady,
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
getStatefulSet: mocks.V1StatefulSet(2, 1),
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "scale unsupported kind",
|
|
args: args{
|
|
name: "gateway_default_nginx_2",
|
|
},
|
|
want: instance.State{
|
|
Name: "gateway_default_nginx_2",
|
|
CurrentReplicas: 0,
|
|
DesiredReplicas: 2,
|
|
Status: instance.Unrecoverable,
|
|
Message: "unsupported kind \"gateway\" must be one of \"deployment\", \"statefulset\"",
|
|
},
|
|
data: data{
|
|
name: "nginx",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
deploymentAPI := mocks.DeploymentMock{}
|
|
statefulsetAPI := mocks.StatefulSetsMock{}
|
|
provider := KubernetesProvider{
|
|
Client: mocks.NewKubernetesAPIClientMock(&deploymentAPI, &statefulsetAPI),
|
|
delimiter: "_",
|
|
}
|
|
|
|
deploymentAPI.On("Get", mock.Anything, tt.data.name, metav1.GetOptions{}).Return(tt.data.getDeployment, nil)
|
|
statefulsetAPI.On("Get", mock.Anything, tt.data.name, metav1.GetOptions{}).Return(tt.data.getStatefulSet, nil)
|
|
|
|
got, err := provider.GetState(context.Background(), tt.args.name)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("KubernetesProvider.GetState() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("KubernetesProvider.GetState() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|