Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge develop to master #49

Merged
merged 11 commits into from
Mar 7, 2019
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
1 change: 1 addition & 0 deletions .release
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
release=1.0.0
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ install:
- go get -u golang.org/x/lint/golint
- curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
- chmod +x get_helm.sh
- sudo ./get_helm.sh
- ./get_helm.sh

before_script:
- hack/verify-gofmt.sh
Expand All @@ -21,4 +21,4 @@ before_script:
- helm lint helm/botkube

script:
- build/docker.sh infracloudio/botkube latest
- make
51 changes: 51 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
IMAGE_REPO=infracloud/botkube
TAG=$(shell cut -d'=' -f2- .release)

.DEFAULT_GOAL := build
.PHONY: release git-tag check-git-status build pre-build tag-image publish

#Docker Tasks
#Make a release
release: check-git-status build tag-image publish git-tag
@echo "Successfully released version $(TAG)"

#Create a git tag
git-tag:
@echo "Creating a git tag"
@git add .
@git commit -m "Bumped to version $(TAG)" ;
@git tag $(TAG) ;
@git push --tags origin master;
@echo 'Git tag pushed successfully' ;

#Check git status
check-git-status:
@echo "Checking git status"
@if [ -n "$(shell git tag | grep $(TAG))" ] ; then echo 'Tag already exists' && exit 1 ; fi
@if [ -z "$(shell git remote -v)" ] ; then echo 'No remote to push tags to' && exit 1 ; fi
@if [ -z "$(shell git config user.email)" ] ; then echo 'Unable to detect git credentials' && exit 1 ; fi

#Build the image
build: pre-build
@echo "Building docker image"
@docker build --build-arg GOOS_VAL=$(shell go env GOOS) --build-arg GOARCH_VAL=$(shell go env GOARCH) -t $(IMAGE_REPO) -f build/Dockerfile --no-cache .
@echo "Docker image build successfully"

#Pre-build checks
pre-build:
@echo "Checking system information"
@if [ -z "$(shell go env GOOS)" ] || [ -z "$(shell go env GOARCH)" ] ; then echo 'Could not determine the system architecture.' && exit 1 ; fi


#Tag images
tag-image:
@echo 'Tagging image'
@docker tag $(IMAGE_REPO) $(IMAGE_REPO):$(TAG)
@docker tag $(IMAGE_REPO) $(IMAGE_REPO):latest

#Docker push image
publish:
@echo "Pushing docker image to repository"
@docker login
@docker push $(IMAGE_REPO):$(TAG)
@docker push $(IMAGE_REPO):latest
25 changes: 16 additions & 9 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
FROM golang:1.11-alpine
# Development image
FROM golang:alpine AS BUILD-ENV

RUN mkdir -p /go/src/app
WORKDIR /go/src/app

CMD ["/botkube"]
ARG GOOS_VAL
ARG GOARCH_VAL

RUN mkdir -p /go/src/github.com/infracloudio/botkube/vendor && \
mkdir -p /go/src/github.com/infracloudio/botkube/cmd && \
Expand All @@ -14,11 +13,19 @@ COPY cmd/ /go/src/github.com/infracloudio/botkube/cmd
COPY pkg/ /go/src/github.com/infracloudio/botkube/pkg

RUN cd /go/src/github.com/infracloudio/botkube/cmd/botkube && \
go build && \
cp /go/src/github.com/infracloudio/botkube/cmd/botkube/botkube /botkube
GOOS=${GOOS_VAL} GOARCH=${GOARCH_VAL} go build -o /go/bin/botkube

# Install kubectl
ENV KUBE_LATEST_VERSION="v1.13.0"

RUN apk add --no-cache ca-certificates bash git \
&& wget -q https://storage.googleapis.com/kubernetes-release/release/${KUBE_LATEST_VERSION}/bin/linux/amd64/kubectl -O /usr/local/bin/kubectl \
&& chmod +x /usr/local/bin/kubectl \
&& chmod +x /usr/local/bin/kubectl

# Production image
FROM alpine

COPY --from=BUILD-ENV /go/bin/botkube /go/bin/botkube
COPY --from=BUILD-ENV /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=BUILD-ENV /usr/local/bin/kubectl /usr/local/bin/kubectl

ENTRYPOINT /go/bin/botkube
9 changes: 0 additions & 9 deletions build/docker.sh

This file was deleted.

2 changes: 0 additions & 2 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,3 @@ settings:
clustername: not-configured
# Set false to disable kubectl commands execution
allowkubectl: false
# Set true only respond to channel in config
checkchannel: false
51 changes: 51 additions & 0 deletions design/multi-cluster.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Multi-cluster Support

#### Assumptions
`@botkube` commands refer to all the commands in the slack bot which currently supports:
- kubectl
- notifier
- ping


### Summary
Add Multi-cluster support for Botkube, where a single bot can monitor multiple clusters and respond to `@botkube` commands with cluster specific results.

### Motivation
Currently in multi-cluster scenario, a Slack bot authenticates all the clusters with a same authentication token. Thus running `@botkube` command returns response from all the configured clusters, irrespective of the slack channel or group. For `@botkube` command execution, we need a particular cluster specific output.

### Design

This design approach adds a flag `--cluster-name` to all `@botkube` commands. Use of that flag is optional in a cluster specific channel.

Botkube `Notifier` commands are restricted to a dedicated channel for a cluster only and `--cluster-name` flag is ignored.

Botkube `ping` command with the `--cluster-name` flag returns `pong` response from the cluster specified in the flag, else you get response from all the clusters. `Ping` command without --cluster-name flag can be used to list all the configured clusters in the slack bot and identify you cluster's name among them.

For `kubectl` commands in a dedicated channel to a cluster, if `--cluster-name` flag is used, it responds with the output for the cluster specified in flag, else it checks if the channel in the request matches the `config.Communications.Slack.Channel` and responds if true else ignores.

For `kubectl` commands in a group, Direct message or channel not dedicated to any cluster, the `--cluster-name` flag is mandatory. The executor checks if the `--cluster-name` flag is present in the request. If yes, it gets the cluster's name from the flag and compares with `c.Settings.ClusterName` from the config file, if it matches then it responds with the required output to the slack bot and if it doesn't match, it ignores the request. And if the `--cluster-name` flag is absent for kubectl commands, it responds to the slack bot saying 'Please specify the cluster-name'.

For example -
```sh
@Botkube get pods --cluster-name={CLUSTER_NAME}
```
where,
`CLUSTER_NAME` is the name of the cluster you want to query.

To get the list of all clusters configured in the slack, you can run the following command in slack.

```sh
@Botkube ping
```

##### Workflow

![Multi_Cluster_Design](workflow.png)


### Drawbacks
The `--cluster-name` flag is mandated for kubectl and notifier commands resulting additional overhead.

### Alternatives
We can add channel specific authentication token or completely dedicate a channel to a particular cluster which requires changes in the slack code.

Binary file added design/workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions helm/botkube/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ replicaCount: 1

image:
repository: infracloud/botkube
tag: "0.4"
tag: "latest"
pullPolicy: Always

nameOverride: ""
Expand Down Expand Up @@ -140,8 +140,6 @@ config:
clustername: not-configured
# Set false to disable kubectl commands execution
allowkubectl: false
# Set true only respond to channel in config
checkchannel: false

resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
Expand Down
1 change: 0 additions & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ type Slack struct {
type Settings struct {
ClusterName string
AllowKubectl bool
CheckChannel bool
}

// New returns new Config
Expand Down
13 changes: 7 additions & 6 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package controller

import (
"fmt"
"os"
"os/signal"
"strconv"
Expand All @@ -20,13 +21,13 @@ import (
"k8s.io/client-go/tools/cache"
)

var startTime time.Time

const (
controllerStartMsg = "...and now my watch begins! :crossed_swords:"
controllerStopMsg = "my watch has ended!"
controllerStartMsg = "...and now my watch begins for cluster '%s'! :crossed_swords:"
controllerStopMsg = "my watch has ended for cluster '%s'!"
)

var startTime time.Time

func findNamespace(ns string) string {
if ns == "all" {
return apiV1.NamespaceAll
Expand All @@ -39,7 +40,7 @@ func findNamespace(ns string) string {

// RegisterInformers creates new informer controllers to watch k8s resources
func RegisterInformers(c *config.Config) {
sendMessage(controllerStartMsg)
sendMessage(fmt.Sprintf(controllerStartMsg, c.Settings.ClusterName))
startTime = time.Now().Local()

// Get resync period
Expand Down Expand Up @@ -127,7 +128,7 @@ func RegisterInformers(c *config.Config) {
signal.Notify(sigterm, syscall.SIGTERM)
signal.Notify(sigterm, syscall.SIGINT)
<-sigterm
sendMessage(controllerStopMsg)
sendMessage(fmt.Sprintf(controllerStopMsg, c.Settings.ClusterName))
}

func registerEventHandlers(resourceType string, events []string) (handlerFns cache.ResourceEventHandlerFuncs) {
Expand Down
Loading