keel/bot/slack/slack_test.go

337 lines
7.2 KiB
Go

package slack
import (
"fmt"
"os"
"time"
"github.com/nlopes/slack"
"github.com/keel-hq/keel/extension/approval"
"github.com/keel-hq/keel/provider/kubernetes"
"github.com/keel-hq/keel/approvals"
b "github.com/keel-hq/keel/bot"
"github.com/keel-hq/keel/cache/memory"
"github.com/keel-hq/keel/constants"
"github.com/keel-hq/keel/types"
"testing"
testutil "github.com/keel-hq/keel/util/testing"
)
var botMessagesChannel chan *b.BotMessage
var approvalsRespCh chan *b.ApprovalResponse
func New(name, token, channel string,
k8sImplementer kubernetes.Implementer,
approvalsManager approvals.Manager, fi SlackImplementer) *Bot {
approvalsRespCh = make(chan *b.ApprovalResponse)
botMessagesChannel = make(chan *b.BotMessage)
slack := &Bot{}
b.RegisterBot(name, slack)
b.Run(k8sImplementer, approvalsManager)
slack.slackHTTPClient = fi
return slack
}
type fakeProvider struct {
submitted []types.Event
images []*types.TrackedImage
}
func (p *fakeProvider) Submit(event types.Event) error {
p.submitted = append(p.submitted, event)
return nil
}
func (p *fakeProvider) TrackedImages() ([]*types.TrackedImage, error) {
return p.images, nil
}
func (p *fakeProvider) List() []string {
return []string{"fakeprovider"}
}
func (p *fakeProvider) Stop() {
return
}
func (p *fakeProvider) GetName() string {
return "fp"
}
type postedMessage struct {
channel string
text string
params slack.PostMessageParameters
}
type fakeSlackImplementer struct {
postedMessages []postedMessage
}
func (i *fakeSlackImplementer) PostMessage(channel, text string, params slack.PostMessageParameters) (string, string, error) {
i.postedMessages = append(i.postedMessages, postedMessage{
channel: channel,
text: text,
params: params,
})
return "", "", nil
}
func TestBotRequest(t *testing.T) {
f8s := &testutil.FakeK8sImplementer{}
fi := &fakeSlackImplementer{}
mem := memory.NewMemoryCache()
token := os.Getenv(constants.EnvSlackToken)
if token == "" {
t.Skip()
}
am := approvals.New(mem)
New("keel", token, "approvals", f8s, am, fi)
defer b.Stop()
time.Sleep(1 * time.Second)
err := am.Create(&types.Approval{
Identifier: "k8s/project/repo:1.2.3",
VotesRequired: 1,
CurrentVersion: "2.3.4",
NewVersion: "3.4.5",
Event: &types.Event{
Repository: types.Repository{
Name: "project/repo",
Tag: "2.3.4",
},
},
})
if err != nil {
t.Fatalf("unexpected error while creating : %s", err)
}
time.Sleep(1 * time.Second)
if len(fi.postedMessages) != 1 {
t.Errorf("expected to find one message, but got: %d", len(fi.postedMessages))
}
}
func TestProcessApprovedResponse(t *testing.T) {
f8s := &testutil.FakeK8sImplementer{}
fi := &fakeSlackImplementer{}
mem := memory.NewMemoryCache()
token := os.Getenv(constants.EnvSlackToken)
if token == "" {
t.Skip()
}
am := approvals.New(mem)
New("keel", token, "approvals", f8s, am, fi)
defer b.Stop()
time.Sleep(1 * time.Second)
err := am.Create(&types.Approval{
Identifier: "k8s/project/repo:1.2.3",
VotesRequired: 1,
CurrentVersion: "2.3.4",
NewVersion: "3.4.5",
Event: &types.Event{
Repository: types.Repository{
Name: "project/repo",
Tag: "2.3.4",
},
},
})
if err != nil {
t.Fatalf("unexpected error while creating : %s", err)
}
time.Sleep(1 * time.Second)
if len(fi.postedMessages) != 1 {
t.Errorf("expected to find one message")
}
}
func TestProcessApprovalReply(t *testing.T) {
f8s := &testutil.FakeK8sImplementer{}
fi := &fakeSlackImplementer{}
mem := memory.NewMemoryCache()
token := os.Getenv(constants.EnvSlackToken)
if token == "" {
t.Skip()
}
am := approvals.New(mem)
identifier := "k8s/project/repo:1.2.3"
// creating initial approve request
err := am.Create(&types.Approval{
Identifier: identifier,
VotesRequired: 2,
CurrentVersion: "2.3.4",
NewVersion: "3.4.5",
Event: &types.Event{
Repository: types.Repository{
Name: "project/repo",
Tag: "2.3.4",
},
},
})
if err != nil {
t.Fatalf("unexpected error while creating : %s", err)
}
bot := New("keel", token, "approvals", f8s, am, fi)
defer b.Stop()
time.Sleep(1 * time.Second)
// approval resp
bot.approvalsRespCh <- &b.ApprovalResponse{
User: "123",
Status: types.ApprovalStatusApproved,
Text: fmt.Sprintf("%s %s", b.ApprovalResponseKeyword, identifier),
}
time.Sleep(1 * time.Second)
updated, err := am.Get(identifier)
if err != nil {
t.Fatalf("failed to get approval, error: %s", err)
}
if updated.VotesReceived != 1 {
t.Errorf("expected to find 1 received vote, found %d", updated.VotesReceived)
}
if updated.Status() != types.ApprovalStatusPending {
t.Errorf("expected approval to be in status pending but got: %s", updated.Status())
}
if len(fi.postedMessages) != 1 {
t.Errorf("expected to find one message")
}
}
func TestProcessRejectedReply(t *testing.T) {
f8s := &testutil.FakeK8sImplementer{}
fi := &fakeSlackImplementer{}
mem := memory.NewMemoryCache()
token := os.Getenv(constants.EnvSlackToken)
if token == "" {
t.Skip()
}
identifier := "k8s/project/repo:1.2.3"
am := approvals.New(mem)
// creating initial approve request
err := am.Create(&types.Approval{
Identifier: identifier,
VotesRequired: 2,
CurrentVersion: "2.3.4",
NewVersion: "3.4.5",
Event: &types.Event{
Repository: types.Repository{
Name: "project/repo",
Tag: "2.3.4",
},
},
})
if err != nil {
t.Fatalf("unexpected error while creating : %s", err)
}
bot := New("keel", "random", "approvals", f8s, am, fi)
defer b.Stop()
collector := approval.New()
collector.Configure(am)
time.Sleep(1 * time.Second)
// approval resp
bot.approvalsRespCh <- &b.ApprovalResponse{
User: "123",
Status: types.ApprovalStatusRejected,
Text: fmt.Sprintf("%s %s", b.RejectResponseKeyword, identifier),
}
time.Sleep(1 * time.Second)
updated, err := am.Get(identifier)
if err != nil {
t.Fatalf("failed to get approval, error: %s", err)
}
if updated.VotesReceived != 0 {
t.Errorf("expected to find 0 received vote, found %d", updated.VotesReceived)
}
if updated.Status() != types.ApprovalStatusRejected {
t.Errorf("expected approval to be in status rejected but got: %s", updated.Status())
}
fmt.Println(updated.Status())
if len(fi.postedMessages) != 1 {
t.Errorf("expected to find one message")
}
}
func TestIsApproval(t *testing.T) {
// f8s := &testutil.FakeK8sImplementer{}
// mem := memory.NewMemoryCache(100*time.Hour, 100*time.Hour, 100*time.Hour)
//
// identifier := "k8s/project/repo:1.2.3"
//
// am := approvals.New(mem)
// // creating initial approve request
// err := am.Create(&types.Approval{
// Identifier: identifier,
// VotesRequired: 2,
// CurrentVersion: "2.3.4",
// NewVersion: "3.4.5",
// Event: &types.Event{
// Repository: types.Repository{
// Name: "project/repo",
// Tag: "2.3.4",
// },
// },
// })
//
// if err != nil {
// t.Fatalf("unexpected error while creating : %s", err)
// }
// bot := New("keel", "random", "approvals", f8s, am, fi)
event := &slack.MessageEvent{
Msg: slack.Msg{
Channel: "approvals",
User: "user-x",
},
}
_, isApproval := b.IsApproval(event.User, "approve k8s/project/repo:1.2.3")
if !isApproval {
t.Errorf("event expected to be an approval")
}
}