Статьи

Создание прокси Slack Docker в Go — часть 2

В предыдущей статье мы рассмотрели, как можно легко создать slack-docker-proxy, используя go и пару небольших библиотек. Во второй статье мы покажем, как легко добавлять дополнительные команды, и рассмотрим, как докеризировать этот компонент, чтобы вы могли легко запустить его в демоне docker. Обратите внимание, что полные источники для различных файлов go, конечно, можно найти в репозитории slack-proxy github.

Запуск го приложения в докере

Давайте сначала посмотрим, как мы можем развернуть и запустить этот прокси. Мы увидели, что можем запустить его прямо из командной строки следующим образом:

1
2
3
4
$ export GOPATH=directory/where/you/cloned/the/repo
$ go get github.com/fsouza/go-dockerclient
$ go build src/github.com/josdirksen/slackproxy/slack-proxy.go
$ ./slackproxy -config ./resources/config.json

Но это не самый практичный способ сделать это. И поскольку мы уже используем это для мониторинга докера, почему бы просто не запустить этот прокси и внутри докера.

Для запуска приложения go-lang в Docker мы можем использовать два разных подхода. Мы можем скомпилировать приложение из командной строки и просто скопировать его в образ докера, или мы можем добавить источники к образу, который содержит все необходимое для работы, и скомпилировать его как шаг при создании нашего образа докера. Мы пойдем на этот второй подход.

Мы показали файл Docker, который мы будем использовать для этого здесь:

01
02
03
04
05
06
07
08
09
10
11
12
FROM golang:latest
COPY src/ /go/src/
COPY resources/config.json /
EXPOSE 9000
 
# If external packages are needed, install them manually. Not needed if installed in the GOPATH
RUN go get github.com/fsouza/go-dockerclient && go install github.com/fsouza/go-dockerclient
 
WORKDIR src
RUN go build -o /app/main github.com/josdirksen/slackproxy/slack-proxy.go
 
CMD ["/app/main", "--config", "/config.json"]

Шаги должны быть довольно очевидными. Мы проверяем, находятся ли источники в том месте, которое ожидает образ докера (папка / go / src), устанавливаем все внешние зависимости и просто запускаем ‘сборку докера’. Что приводит к следующему выводу:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ docker build .
Sending build context to Docker daemon 203.8 kB
Step 1 : FROM golang:latest
 ---> bc422006801e
Step 2 : COPY src/ /go/src/
 ---> Using cache
 ---> a7c813facaf8
Step 3 : COPY resources/config.json /
 ---> Using cache
 ---> b6fd55de16f6
Step 4 : EXPOSE 9000
 ---> Using cache
 ---> d30199bcc59a
Step 5 : WORKDIR /go/src
 ---> Using cache
 ---> e861b557571d
Step 6 : RUN go get github.com/fsouza/go-dockerclient && go install github.com/fsouza/go-dockerclient
 ---> Running in 6f712526bb99
 ---> 76cecb4c7a19
Removing intermediate container 6f712526bb99
Step 7 : RUN go build -o /app/main github.com/josdirksen/slackproxy/slack-proxy.go
 ---> Running in 77c092d1bcf2
 ---> f7ca02665f94
Removing intermediate container 77c092d1bcf2
Step 8 : CMD /app/main --config /config.json
 ---> Running in 0bbeb60ca608
 ---> ebd9d3fe8ce7
Removing intermediate container 0bbeb60ca608
Successfully built ebd9d3fe8ce7

Полученное изображение теперь можно запустить так:

1
2
$ docker run 94abcb31af14
{5cLHiZjpWaRDb0fP6ka02XCR {[{local tcp://192.168.99.100:2376 true /Users/jos/.docker/machine/machines/eris ca.pem cert.pem key.pem}]}}

Или загрузите в свой локальный реестр, отметив его:

1
docker tag 94abcb31af14 my.own.registry/slack-proxy:latest

Расширение с новой функциональностью

Расширить этот прокси с новой функциональностью действительно легко. Распространенный сценарий, который у нас есть, заключается в том, что после того, как мы что-то развернули и все перестало работать, мы можем быстро проверить файлы журнала. Теперь войти в систему и использовать Docker Log не так сложно, но это займет пару шагов. Поэтому мы добавим поддержку для просмотра файлов журналов прямо из Slack. Сначала мы определим функцию в файле dockerCommandHandlers.go.

1
2
3
4
5
6
7
8
func handleLogsCommand(client *docker.Client, cmd *Command, w http.ResponseWriter) {
    var tail = "all"
    if (len(cmd.OtherArguments) == 2) {
        tail = cmd.OtherArguments[1]
    }
    logoptions := docker.LogsOptions{Container: cmd.OtherArguments[0], Stdout: true, Stderr: true, Follow: false, Tail: tail, OutputStream: w, ErrorStream: w}
    client.Logs(logoptions)
}

Обратите внимание, что мы еще раз не делаем никакой проверки ввода. Мы просто предполагаем, что передано правильное количество аргументов. Теперь, когда у нас есть функция, мы обновляем функцию HandleCommand в том же файле следующим образом:

01
02
03
04
05
06
07
08
09
10
func (dh DockerHandler) HandleCommand(cmdToExecute *Command, w http.ResponseWriter) {
    client := setupDockerClient(cmdToExecute.Environment)
 
    fmt.Printf("%+v\n", cmdToExecute)
 
    switch cmdToExecute.SlackCommand {
    case "ps" : handlePsCommand(client, w)
    case "logs" : handleLogsCommand(client, cmdToExecute, w)
    case "imgs" : handleListImagesCommand(client, w)
    }

И мы сделали. Теперь, когда вызов сделан так:

01
02
03
04
05
06
07
08
09
10
11
12
13
$ curl 'http://localhost:9000/handleSlackCommand' -H 'Content-Type: application/x-www-form-urlencoded' --data
   'token=5cLHiZjpWaRDb0fP6ka02XCR&team_id=T0001&team_domain=example&channel_id=C2147483705&channel_name=test&user_id=jos,nd=docker&text=local+logs+669265a13436+10'
  
> 2016/02/07 18:48:04 [WARN] agent: Check 'service:wiremock' is now warning
> 2016/02/07 18:48:09 [WARN] agent: Check 'service:dag-storage' is now warning
> 2016/02/07 18:48:17 [WARN] agent: Check 'service:wiremock' is now warning
> 2016/02/07 18:48:19 [WARN] agent: Check 'service:dag-storage' is now warning
> 2016/02/07 18:48:29 [WARN] agent: Check 'service:dag-storage' is now warning
> 2016/02/07 18:48:30 [WARN] agent: Check 'service:wiremock' is now warning
> 2016/02/07 18:48:39 [WARN] agent: Check 'service:dag-storage' is now warning
> 2016/02/07 18:48:43 [WARN] agent: Check 'service:wiremock' is now warning
> 2016/02/07 18:48:49 [WARN] agent: Check 'service:dag-storage' is now warning
> 2016/02/07 18:48:56 [WARN] agent: Check 'service:wiremock' is now warning

Мы возвращаем последние 10 записей журнала для контейнера с идентификатором 669265a13436.

Или, если вы более склонны использовать Почтальон.

Почтальон-журналы

Расширение помимо докера

До сих пор мы рассматривали докер только через этот минимальный прокси. Экспонировать другие сервисы, компоненты и источники информации с помощью этой настройки на самом деле очень просто. В качестве примера давайте напишем пару команд, которые предоставляют информацию о хосте, на котором работает slack-прокси. Для этого мы сначала добавим новый CommandHandler:

1
2
3
4
5
6
7
8
9
func handleHostCommand(w http.ResponseWriter) {
    var buffer bytes.Buffer
 
    info, _ := host.HostInfo()
    buffer.WriteString(fmt.Sprintf("Boottime: %v\n", info.BootTime))
    buffer.WriteString(fmt.Sprintf("Hostname: %v\n", info.Hostname))
    buffer.WriteString(fmt.Sprintf("Uptime: %v\n", info.Uptime))
 
    io.WriteString(w, buffer.String())

Если вы посмотрели, как мы настроили обработчик докера, то этот не должен удивлять. Мы используем простой переключатель, чтобы соответствовать команде, которую нам нужно выполнить, и в этом случае используем библиотеку gopsutil для возврата информации о файловой системе. Обратите внимание, что если вы хотите запустить это без докера, сначала вы должны выполнить «go get github.com/shirou/gopsutil». Поскольку мы добавили дополнительный обработчик команд, нам также нужно внести небольшое изменение в функцию GetHandler из handlerFactory:

1
2
3
4
5
6
7
func GetHandler(handlerName string, config *config.Configuration) CommandHandler {
    switch handlerName {
    case "docker": return NewDockerHandler(config)
    case "system" : return NewSystemHandler()
    default: return NewDummyHandler()
    }
}

С этим изменением, когда команда системная, мы возвращаем только что созданный обработчик, а если команда docker, мы возвращаем тот, который может обрабатывать команды Docker. Чтобы увидеть это в действии, вы можете использовать следующую команду curl для информации о памяти:

1
2
3
$ curl 'http://localhost:9000/handleSlackCommand' -H 'Content-Type: application/x-www-form-urlencoded' --data 'token=5cLHiZjpWaRDb0fP6ka02XCR&team_id=T0001&team_domain=example&channel_id=C2147483705&channel_name=test&user_id=jos,nd=system&text=local+mem'
  
> Total: 17179869184, Free:41549824, UsedPercent:65.031576

И для проверки информации о хосте используйте это:

1
2
3
$ curl 'http://localhost:9000/handleSlackCommand' -H 'Content-Type: application/x-www-form-urlencoded' --data 'token=5cLHiZjpWaRDb0fP6ka02XCR&team_id=T0001&team_domain=example&channel_id=C2147483705&channel_name=test&user_id=jos,nd=system&text=local+host'
  
> Boottime: 1453982905Hostname: Joss-MacBook-Pro.localUptime: 889269%

И с этим мы в конце этой статьи на slack / docker (и других источниках) с go-lang. Вы можете найти полные источники для этой статьи здесь . И если у вас есть предложения, пожалуйста, дайте мне знать.

Ссылка: Создайте прокси Slack Docker в Go — часть 2 от нашего партнера JCG Йоса Дирксена из блога Smart Java .