Skip to content

Commit

Permalink
Merge pull request #122 from keel-hq/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
rusenask authored Dec 12, 2017
2 parents ce00b25 + aab4eef commit 42c242d
Show file tree
Hide file tree
Showing 994 changed files with 152,293 additions and 34,189 deletions.
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM golang:1.8.3
FROM golang:1.9.2
COPY . /go/src/github.com/keel-hq/keel
WORKDIR /go/src/github.com/keel-hq/keel
RUN make build
RUN make install

FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=0 /go/src/github.com/keel-hq/keel/keel /bin/keel
COPY --from=0 /go/bin/keel /bin/keel
ENTRYPOINT ["/bin/keel"]

EXPOSE 9300
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ test:

build:
@echo "++ Building keel"
CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags "$(LDFLAGS)" -o keel .
CGO_ENABLED=0 GOOS=linux cd cmd/keel && go build -a -tags netgo -ldflags "$(LDFLAGS) -w -s" -o keel .

install:
@echo "++ Installing keel"
CGO_ENABLED=0 GOOS=linux go install -ldflags "$(LDFLAGS) -w -s" github.com/keel-hq/keel/cmd/keel

image:
docker build -t karolisr/keel:alpha -f Dockerfile .
Expand Down
29 changes: 23 additions & 6 deletions bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,15 @@ type Bot struct {
approvalsRespCh chan *approvalResponse

approvalsManager approvals.Manager
approvalsChannel string // slack approvals channel name

k8sImplementer kubernetes.Implementer

ctx context.Context
}

// New - create new bot instance
func New(name, token string, k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) *Bot {
func New(name, token, approvalsChannel string, k8sImplementer kubernetes.Implementer, approvalsManager approvals.Manager) *Bot {
client := slack.New(token)

bot := &Bot{
Expand All @@ -95,6 +96,7 @@ func New(name, token string, k8sImplementer kubernetes.Implementer, approvalsMan
k8sImplementer: k8sImplementer,
name: name,
approvalsManager: approvalsManager,
approvalsChannel: approvalsChannel,
approvalsRespCh: make(chan *approvalResponse), // don't add buffer to make it blocking
}

Expand Down Expand Up @@ -201,7 +203,7 @@ func (b *Bot) postMessage(title, message, color string, fields []slack.Attachmen
},
}

_, _, err := b.slackHTTPClient.PostMessage("general", "", params)
_, _, err := b.slackHTTPClient.PostMessage(b.approvalsChannel, "", params)
if err != nil {
log.WithFields(log.Fields{
"error": err,
Expand Down Expand Up @@ -230,6 +232,17 @@ func (b *Bot) isApproval(event *slack.MessageEvent, eventText string) (resp *app
return nil, false
}

// TODO(k): cache results in a map or get this info on startup. Although
// if channel was then recreated (unlikely), we would miss results
func (b *Bot) isApprovalsChannel(event *slack.MessageEvent) bool {
for _, ch := range b.slackRTM.GetInfo().Channels {
if ch.ID == event.Channel && ch.Name == b.approvalsChannel {
return true
}
}
return false
}

func (b *Bot) handleMessage(event *slack.MessageEvent) {
if event.BotID != "" || event.User == "" || event.SubType == "bot_message" {
log.WithFields(log.Fields{
Expand All @@ -247,10 +260,14 @@ func (b *Bot) handleMessage(event *slack.MessageEvent) {
}

eventText = b.trimBot(eventText)
approval, ok := b.isApproval(event, eventText)
if ok {
b.approvalsRespCh <- approval
return

// only accepting approvals from approvals channel
if b.isApprovalsChannel(event) {
approval, ok := b.isApproval(event, eventText)
if ok {
b.approvalsRespCh <- approval
return
}
}

// Responses that are just a canned string response
Expand Down
47 changes: 43 additions & 4 deletions bot/bot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestBotRequest(t *testing.T) {

am := approvals.New(mem, codecs.DefaultSerializer())

bot := New("keel", token, f8s, am)
bot := New("keel", token, "approvals", f8s, am)
// replacing slack client so we can receive webhooks
bot.slackHTTPClient = fi

Expand Down Expand Up @@ -126,7 +126,7 @@ func TestProcessApprovedResponse(t *testing.T) {

am := approvals.New(mem, codecs.DefaultSerializer())

bot := New("keel", token, f8s, am)
bot := New("keel", token, "approvals", f8s, am)
// replacing slack client so we can receive webhooks
bot.slackHTTPClient = fi

Expand Down Expand Up @@ -196,7 +196,7 @@ func TestProcessApprovalReply(t *testing.T) {
t.Fatalf("unexpected error while creating : %s", err)
}

bot := New("keel", token, f8s, am)
bot := New("keel", token, "approvals", f8s, am)
// replacing slack client so we can receive webhooks
bot.slackHTTPClient = fi

Expand Down Expand Up @@ -267,7 +267,7 @@ func TestProcessRejectedReply(t *testing.T) {
t.Fatalf("unexpected error while creating : %s", err)
}

bot := New("keel", "random", f8s, am)
bot := New("keel", "random", "approvals", f8s, am)

collector := approval.New()
collector.Configure(am)
Expand Down Expand Up @@ -313,3 +313,42 @@ func TestProcessRejectedReply(t *testing.T) {
}

}

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, codecs.DefaultSerializer())
// 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)

_, isApproval := bot.isApproval(&slack.MessageEvent{
Msg: slack.Msg{
Channel: "approvals",
User: "user-x",
},
}, "approve k8s/project/repo:1.2.3")

if !isApproval {
t.Errorf("event expected to be an approval")
}
}
29 changes: 25 additions & 4 deletions main.go → cmd/keel/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package main
import (
"os"
"os/signal"
"path/filepath"
"time"

"context"

netContext "golang.org/x/net/context"
kingpin "gopkg.in/alecthomas/kingpin.v2"

"github.com/keel-hq/keel/approvals"
"github.com/keel-hq/keel/bot"
Expand Down Expand Up @@ -57,6 +59,14 @@ const EnvDebug = "DEBUG"
func main() {

ver := version.GetKeelVersion()

inCluster := kingpin.Flag("incluster", "use in cluster configuration (defaults to 'true'), use '--no-incluster' if running outside of the cluster").Default("true").Bool()
kubeconfig := kingpin.Flag("kubeconfig", "path to kubeconfig (if not in running inside a cluster)").Default(filepath.Join(os.Getenv("HOME"), ".kube", "config")).String()

kingpin.UsageTemplate(kingpin.CompactUsageTemplate).Version(ver.Version)
kingpin.CommandLine.Help = "Automated Kubernetes deployment updates. Learn more on https://keel.sh."
kingpin.Parse()

log.WithFields(log.Fields{
"os": ver.OS,
"build_date": ver.BuildDate,
Expand Down Expand Up @@ -100,12 +110,16 @@ func main() {
}

// getting k8s provider
k8sCfg := &kubernetes.Opts{}
k8sCfg := &kubernetes.Opts{
ConfigPath: *kubeconfig,
}

if os.Getenv(EnvKubernetesConfig) != "" {
k8sCfg.ConfigPath = os.Getenv(EnvKubernetesConfig)
} else {
k8sCfg.InCluster = true
}

k8sCfg.InCluster = *inCluster

implementer, err := kubernetes.NewKubernetesImplementer(k8sCfg)
if err != nil {
log.WithFields(log.Fields{
Expand Down Expand Up @@ -175,6 +189,7 @@ func main() {
}()

<-cleanupDone

}

// setupProviders - setting up available providers. New providers should be initialised here and added to
Expand Down Expand Up @@ -215,7 +230,13 @@ func setupBot(k8sImplementer kubernetes.Implementer, approvalsManager approvals.
}

token := os.Getenv(constants.EnvSlackToken)
slackBot := bot.New(botName, token, k8sImplementer, approvalsManager)

approvalsChannel := "general"
if os.Getenv(constants.EnvSlackApprovalsChannel) != "" {
approvalsChannel = os.Getenv(constants.EnvSlackApprovalsChannel)
}

slackBot := bot.New(botName, token, approvalsChannel, k8sImplementer, approvalsManager)

ctx, cancel := context.WithCancel(context.Background())

Expand Down
1 change: 1 addition & 0 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const (
EnvSlackToken = "SLACK_TOKEN"
EnvSlackBotName = "SLACK_BOT_NAME"
EnvSlackChannels = "SLACK_CHANNELS"
EnvSlackApprovalsChannel = "SLACK_APPROVALS_CHANNEL"
)

// EnvNotificationLevel - minimum level for notifications, defaults to info
Expand Down
34 changes: 20 additions & 14 deletions glide.lock

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

5 changes: 5 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ import:
version: ab5485076ff3407ad2d02db054635913f017b0ed
subpackages:
- context
- package: golang.org/x/sys
version: 07c182904dbd53199946ba614a412c61d3c548f5
subpackages:
- unix
- windows
# - package: google.golang.org/api
# subpackages:
# - option
Expand Down
Loading

0 comments on commit 42c242d

Please sign in to comment.