367 lines
8.7 KiB
Go
367 lines
8.7 KiB
Go
package approvals
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/keel-hq/keel/cache/memory"
|
|
"github.com/keel-hq/keel/types"
|
|
"github.com/keel-hq/keel/util/codecs"
|
|
)
|
|
|
|
func TestCreateApproval(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
stored, err := am.Get("xxx/app-1")
|
|
if err != nil {
|
|
t.Fatalf("failed to get approval: %s", err)
|
|
}
|
|
|
|
if stored.CurrentVersion != "1.2.3" {
|
|
t.Errorf("unexpected version: %s", stored.CurrentVersion)
|
|
}
|
|
}
|
|
|
|
func TestDeleteApproval(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
err = am.Delete("xxx/app-1")
|
|
if err != nil {
|
|
t.Errorf("failed to delete approval: %s", err)
|
|
}
|
|
|
|
_, err = am.Get("xxx/app-1")
|
|
if err == nil {
|
|
t.Errorf("expected to get an error when retrieving deleted approval")
|
|
}
|
|
|
|
}
|
|
|
|
func TestUpdateApproval(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
VotesRequired: 1,
|
|
VotesReceived: 0,
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
Event: &types.Event{
|
|
Repository: types.Repository{
|
|
Name: "very/repo",
|
|
Tag: "1.2.5",
|
|
},
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
ch, err := am.SubscribeApproved(ctx)
|
|
if err != nil {
|
|
t.Fatalf("failed to subscribe: %s", err)
|
|
}
|
|
|
|
err = am.Update(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
VotesRequired: 1,
|
|
VotesReceived: 1,
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
Event: &types.Event{
|
|
Repository: types.Repository{
|
|
Name: "very/repo",
|
|
Tag: "1.2.5",
|
|
},
|
|
},
|
|
})
|
|
|
|
approved := <-ch
|
|
|
|
if approved.Event.Repository.Name != "very/repo" {
|
|
t.Errorf("unexpected repo name in re-submitted event: %s", approved.Event.Repository.Name)
|
|
}
|
|
if approved.Event.Repository.Tag != "1.2.5" {
|
|
t.Errorf("unexpected repo tag in re-submitted event: %s", approved.Event.Repository.Tag)
|
|
}
|
|
}
|
|
|
|
func TestUpdateApprovalRejected(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
VotesRequired: 1,
|
|
VotesReceived: 0,
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
Event: &types.Event{
|
|
Repository: types.Repository{
|
|
Name: "very/repo",
|
|
Tag: "1.2.5",
|
|
},
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
ch, err := am.SubscribeApproved(ctx)
|
|
if err != nil {
|
|
t.Fatalf("failed to subscribe: %s", err)
|
|
}
|
|
|
|
// rejecting
|
|
err = am.Update(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
VotesRequired: 1,
|
|
VotesReceived: 0,
|
|
Rejected: true,
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
Event: &types.Event{
|
|
Repository: types.Repository{
|
|
Name: "very/repo",
|
|
Tag: "1.2.5",
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("failed to update approval: %s", err)
|
|
}
|
|
|
|
// sending vote
|
|
err = am.Update(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
VotesRequired: 1,
|
|
VotesReceived: 1,
|
|
Rejected: true,
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
Event: &types.Event{
|
|
Repository: types.Repository{
|
|
Name: "very/repo",
|
|
Tag: "1.2.5",
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("failed to update approval: %s", err)
|
|
}
|
|
|
|
select {
|
|
case <-time.After(500 * time.Millisecond):
|
|
// success
|
|
return
|
|
case approval := <-ch:
|
|
t.Errorf("unexpected approval got: %s", approval.Identifier)
|
|
}
|
|
|
|
}
|
|
|
|
func TestApprove(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1:1.2.5",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
VotesRequired: 2,
|
|
VotesReceived: 0,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
am.Approve("xxx/app-1:1.2.5", "warda")
|
|
|
|
stored, err := am.Get("xxx/app-1:1.2.5")
|
|
if err != nil {
|
|
t.Fatalf("failed to get approval: %s", err)
|
|
}
|
|
|
|
if stored.VotesReceived != 1 {
|
|
t.Errorf("unexpected number of received votes: %d", stored.VotesReceived)
|
|
}
|
|
}
|
|
|
|
func TestApproveTwiceSameVoter(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1:1.2.5",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
VotesRequired: 2,
|
|
VotesReceived: 0,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
am.Approve("xxx/app-1:1.2.5", "warda")
|
|
am.Approve("xxx/app-1:1.2.5", "warda")
|
|
|
|
stored, err := am.Get("xxx/app-1:1.2.5")
|
|
if err != nil {
|
|
t.Fatalf("failed to get approval: %s", err)
|
|
}
|
|
|
|
// should still be the same
|
|
if stored.VotesReceived != 1 {
|
|
t.Errorf("unexpected number of received votes: %d", stored.VotesReceived)
|
|
}
|
|
}
|
|
|
|
func TestApproveTwoVoters(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1:1.2.5",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
VotesRequired: 2,
|
|
VotesReceived: 0,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
am.Approve("xxx/app-1:1.2.5", "w")
|
|
am.Approve("xxx/app-1:1.2.5", "k")
|
|
|
|
stored, err := am.Get("xxx/app-1:1.2.5")
|
|
if err != nil {
|
|
t.Fatalf("failed to get approval: %s", err)
|
|
}
|
|
|
|
// should still be the same
|
|
if stored.VotesReceived != 2 {
|
|
t.Errorf("unexpected number of received votes: %d", stored.VotesReceived)
|
|
}
|
|
}
|
|
|
|
func TestReject(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
Deadline: time.Now().Add(5 * time.Minute),
|
|
VotesRequired: 2,
|
|
VotesReceived: 0,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
am.Reject("xxx/app-1")
|
|
|
|
stored, err := am.Get("xxx/app-1")
|
|
if err != nil {
|
|
t.Fatalf("failed to get approval: %s", err)
|
|
}
|
|
|
|
if !stored.Rejected {
|
|
t.Errorf("unexpected approval to be rejected")
|
|
}
|
|
}
|
|
|
|
func TestExpire(t *testing.T) {
|
|
mem := memory.NewMemoryCache(100*time.Millisecond, 100*time.Millisecond, 10*time.Millisecond)
|
|
|
|
am := New(mem, codecs.DefaultSerializer())
|
|
|
|
err := am.Create(&types.Approval{
|
|
Provider: types.ProviderTypeKubernetes,
|
|
Identifier: "xxx/app-1",
|
|
CurrentVersion: "1.2.3",
|
|
NewVersion: "1.2.5",
|
|
Deadline: time.Now().Add(-5 * time.Minute),
|
|
VotesRequired: 2,
|
|
VotesReceived: 0,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatalf("failed to create approval: %s", err)
|
|
}
|
|
|
|
err = am.expireEntries()
|
|
if err != nil {
|
|
t.Errorf("got error while expiring entries: %s", err)
|
|
}
|
|
|
|
_, err = am.Get("xxx/app-1")
|
|
if err == nil {
|
|
t.Errorf("expected approval to be deleted but didn't get an error")
|
|
}
|
|
}
|