mirror of
https://github.com/kyverno/policy-reporter.git
synced 2024-12-15 17:50:58 +00:00
Merge pull request #341 from kyverno/telegram-target
Telegram push target support
This commit is contained in:
commit
83366ace58
9 changed files with 478 additions and 2 deletions
|
@ -150,6 +150,33 @@ webhook:
|
|||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
|
||||
telegram:
|
||||
token: {{ .Values.target.telegram.token | quote }}
|
||||
chatID: {{ .Values.target.telegram.chatID | quote }}
|
||||
host: {{ .Values.target.telegram.host | quote }}
|
||||
certificate: {{ .Values.target.telegram.certificate | quote }}
|
||||
skipTLS: {{ .Values.target.telegram.skipTLS }}
|
||||
secretRef: {{ .Values.target.telegram.secretRef | quote }}
|
||||
mountedSecret: {{ .Values.target.telegram.mountedSecret | quote }}
|
||||
minimumPriority: {{ .Values.target.telegram.minimumPriority | quote }}
|
||||
skipExistingOnStartup: {{ .Values.target.telegram.skipExistingOnStartup }}
|
||||
{{- with .Values.target.telegram.sources }}
|
||||
sources:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.target.telegram.customFields }}
|
||||
customFields:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.target.telegram.filter }}
|
||||
filter:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.target.telegram.channels }}
|
||||
channels:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
|
||||
ui:
|
||||
host: {{ include "policyreporter.uihost" . }}
|
||||
certificate: {{ .Values.target.ui.certificate | quote }}
|
||||
|
|
|
@ -483,6 +483,37 @@ target:
|
|||
# add additional webhook channels with different configurations and filters
|
||||
channels: []
|
||||
|
||||
telegram:
|
||||
# telegram bot token
|
||||
token: ""
|
||||
# telegram chat id
|
||||
chatID: ""
|
||||
# optional telegram proxy host
|
||||
host: ""
|
||||
# path to your custom certificate
|
||||
# can be added under extraVolumes
|
||||
certificate: ""
|
||||
# skip TLS verification if necessary
|
||||
skipTLS: false
|
||||
# receive the host and/or token from an existing secret, the token is added as Authorization header
|
||||
secretRef: ""
|
||||
# Mounted secret path by Secrets Controller, secret should be in json format
|
||||
mountedSecret: ""
|
||||
# additional http headers
|
||||
headers: {}
|
||||
# minimum priority "" < info < warning < critical < error
|
||||
minimumPriority: ""
|
||||
# list of sources which should send to telegram
|
||||
sources: []
|
||||
# Skip already existing PolicyReportResults on startup
|
||||
skipExistingOnStartup: true
|
||||
# Added as additional properties to each notification
|
||||
customFields: {}
|
||||
# filter results send by namespaces, policies and priorities
|
||||
filter: {}
|
||||
# add additional telegram channels with different configurations and filters
|
||||
channels: []
|
||||
|
||||
s3:
|
||||
# S3 access key
|
||||
accessKeyID: ""
|
||||
|
|
|
@ -103,6 +103,18 @@ type Webhook struct {
|
|||
Channels []Webhook `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Telegram configuration
|
||||
type Telegram struct {
|
||||
TargetBaseOptions `mapstructure:",squash"`
|
||||
Host string `mapstructure:"host"`
|
||||
Token string `mapstructure:"token"`
|
||||
ChatID string `mapstructure:"chatID"`
|
||||
SkipTLS bool `mapstructure:"skipTLS"`
|
||||
Certificate string `mapstructure:"certificate"`
|
||||
Headers map[string]string `mapstructure:"headers"`
|
||||
Channels []Telegram `mapstructure:"channels"`
|
||||
}
|
||||
|
||||
type AWSConfig struct {
|
||||
AccessKeyID string `mapstructure:"accessKeyID"`
|
||||
SecretAccessKey string `mapstructure:"secretAccessKey"`
|
||||
|
@ -282,6 +294,7 @@ type Config struct {
|
|||
GCS GCS `mapstructure:"gcs"`
|
||||
UI UI `mapstructure:"ui"`
|
||||
Webhook Webhook `mapstructure:"webhook"`
|
||||
Telegram Telegram `mapstructure:"telegram"`
|
||||
API API `mapstructure:"api"`
|
||||
WorkerCount int `mapstructure:"worker"`
|
||||
DBFile string `mapstructure:"dbfile"`
|
||||
|
|
|
@ -279,6 +279,7 @@ func (r *Resolver) TargetClients() []target.Client {
|
|||
clients = append(clients, factory.SecurityHubs(r.config.SecurityHub)...)
|
||||
clients = append(clients, factory.WebhookClients(r.config.Webhook)...)
|
||||
clients = append(clients, factory.GCSClients(r.config.GCS)...)
|
||||
clients = append(clients, factory.TelegramClients(r.config.Telegram)...)
|
||||
|
||||
if ui := factory.UIClient(r.config.UI); ui != nil {
|
||||
clients = append(clients, ui)
|
||||
|
|
|
@ -175,13 +175,22 @@ var testConfig = &config.Config{
|
|||
Encryption: "ssl/tls",
|
||||
},
|
||||
},
|
||||
Telegram: config.Telegram{
|
||||
Token: "XXX",
|
||||
ChatID: "123456",
|
||||
Channels: []config.Telegram{
|
||||
{
|
||||
ChatID: "1234567",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func Test_ResolveTargets(t *testing.T) {
|
||||
resolver := config.NewResolver(testConfig, &rest.Config{})
|
||||
|
||||
if count := len(resolver.TargetClients()); count != 22 {
|
||||
t.Errorf("Expected 22 Clients, got %d", count)
|
||||
if count := len(resolver.TargetClients()); count != 24 {
|
||||
t.Errorf("Expected 24 Clients, got %d", count)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"go.uber.org/zap"
|
||||
|
@ -23,6 +24,7 @@ import (
|
|||
"github.com/kyverno/policy-reporter/pkg/target/securityhub"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/slack"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/teams"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/telegram"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/ui"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/webhook"
|
||||
)
|
||||
|
@ -284,6 +286,29 @@ func (f *TargetFactory) GCSClients(config GCS) []target.Client {
|
|||
return clients
|
||||
}
|
||||
|
||||
// TelegramClients resolver method
|
||||
func (f *TargetFactory) TelegramClients(config Telegram) []target.Client {
|
||||
clients := make([]target.Client, 0)
|
||||
if config.Name == "" {
|
||||
config.Name = "Telegram"
|
||||
}
|
||||
|
||||
if es := f.createTelegramClient(config, Telegram{}); es != nil {
|
||||
clients = append(clients, es)
|
||||
}
|
||||
for i, channel := range config.Channels {
|
||||
if channel.Name == "" {
|
||||
channel.Name = fmt.Sprintf("Webhook Channel %d", i+1)
|
||||
}
|
||||
|
||||
if es := f.createTelegramClient(channel, config); es != nil {
|
||||
clients = append(clients, es)
|
||||
}
|
||||
}
|
||||
|
||||
return clients
|
||||
}
|
||||
|
||||
func (f *TargetFactory) createSlackClient(config Slack, parent Slack) target.Client {
|
||||
if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" {
|
||||
f.mapSecretValues(&config, config.SecretRef, config.MountedSecret)
|
||||
|
@ -576,6 +601,73 @@ func (f *TargetFactory) createWebhookClient(config Webhook, parent Webhook) targ
|
|||
})
|
||||
}
|
||||
|
||||
func (f *TargetFactory) createTelegramClient(config Telegram, parent Telegram) target.Client {
|
||||
if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" {
|
||||
f.mapSecretValues(&config, config.SecretRef, config.MountedSecret)
|
||||
}
|
||||
|
||||
if config.Token == "" {
|
||||
config.Token = parent.Token
|
||||
}
|
||||
|
||||
if config.ChatID == "" || config.Token == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if config.Host == "" {
|
||||
config.Host = parent.Host
|
||||
}
|
||||
|
||||
if config.Certificate == "" {
|
||||
config.Certificate = parent.Certificate
|
||||
}
|
||||
|
||||
if !config.SkipTLS {
|
||||
config.SkipTLS = parent.SkipTLS
|
||||
}
|
||||
|
||||
if config.MinimumPriority == "" {
|
||||
config.MinimumPriority = parent.MinimumPriority
|
||||
}
|
||||
|
||||
if !config.SkipExisting {
|
||||
config.SkipExisting = parent.SkipExisting
|
||||
}
|
||||
|
||||
if len(parent.Headers) > 0 {
|
||||
headers := map[string]string{}
|
||||
for header, value := range parent.Headers {
|
||||
headers[header] = value
|
||||
}
|
||||
for header, value := range config.Headers {
|
||||
headers[header] = value
|
||||
}
|
||||
|
||||
config.Headers = headers
|
||||
}
|
||||
|
||||
host := "https://api.telegram.org"
|
||||
if config.Host != "" {
|
||||
host = strings.TrimSuffix(config.Host, "/")
|
||||
}
|
||||
|
||||
zap.S().Infof("%s configured", config.Name)
|
||||
|
||||
return telegram.NewClient(telegram.Options{
|
||||
ClientOptions: target.ClientOptions{
|
||||
Name: config.Name,
|
||||
SkipExistingOnStartup: config.SkipExisting,
|
||||
ResultFilter: createResultFilter(config.Filter, config.MinimumPriority, config.Sources),
|
||||
ReportFilter: createReportFilter(config.Filter),
|
||||
},
|
||||
Host: fmt.Sprintf("%s/bot%s/sendMessage", host, config.Token),
|
||||
ChatID: config.ChatID,
|
||||
Headers: config.Headers,
|
||||
CustomFields: config.CustomFields,
|
||||
HTTPClient: http.NewClient(config.Certificate, config.SkipTLS),
|
||||
})
|
||||
}
|
||||
|
||||
func (f *TargetFactory) createS3Client(config S3, parent S3) target.Client {
|
||||
if (config.SecretRef != "" && f.secretClient != nil) || config.MountedSecret != "" {
|
||||
f.mapSecretValues(&config, config.SecretRef, config.MountedSecret)
|
||||
|
@ -959,6 +1051,13 @@ func (f *TargetFactory) mapSecretValues(config any, ref, mountedSecret string) {
|
|||
|
||||
c.Headers["Authorization"] = values.Token
|
||||
}
|
||||
case *Telegram:
|
||||
if values.Token != "" {
|
||||
c.Token = values.Token
|
||||
}
|
||||
if values.Host != "" {
|
||||
c.Host = values.Host
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,12 @@ func Test_ResolveTarget(t *testing.T) {
|
|||
t.Errorf("Expected 2 Client, got %d clients", len(clients))
|
||||
}
|
||||
})
|
||||
t.Run("Telegram", func(t *testing.T) {
|
||||
clients := factory.TelegramClients(testConfig.Telegram)
|
||||
if len(clients) != 2 {
|
||||
t.Errorf("Expected 2 Client, got %d clients", len(clients))
|
||||
}
|
||||
})
|
||||
t.Run("S3", func(t *testing.T) {
|
||||
clients := factory.S3Clients(testConfig.S3)
|
||||
if len(clients) != 2 {
|
||||
|
@ -161,6 +167,11 @@ func Test_ResolveTargetWithoutHost(t *testing.T) {
|
|||
t.Error("Expected Client to be nil if no host is configured")
|
||||
}
|
||||
})
|
||||
t.Run("Telegram", func(t *testing.T) {
|
||||
if len(factory.TelegramClients(config.Telegram{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no chatID is configured")
|
||||
}
|
||||
})
|
||||
t.Run("S3.Endoint", func(t *testing.T) {
|
||||
if len(factory.S3Clients(config.S3{})) != 0 {
|
||||
t.Error("Expected Client to be nil if no endpoint is configured")
|
||||
|
@ -358,6 +369,20 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("Get Telegram Token from Secret", func(t *testing.T) {
|
||||
clients := factory.TelegramClients(config.Telegram{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, ChatID: "1234"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
||||
client := reflect.ValueOf(clients[0]).Elem()
|
||||
|
||||
host := client.FieldByName("host").String()
|
||||
if host != "http://localhost:9200/bottoken/sendMessage" {
|
||||
t.Errorf("Expected host with token from secret, got %s", host)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get S3 values from Secret", func(t *testing.T) {
|
||||
clients := factory.S3Clients(config.S3{TargetBaseOptions: config.TargetBaseOptions{SecretRef: secretName}, AWSConfig: config.AWSConfig{Endpoint: "endoint", Region: "region"}, Bucket: "bucket"})
|
||||
if len(clients) != 1 {
|
||||
|
@ -458,6 +483,19 @@ func Test_GetValuesFromSecret(t *testing.T) {
|
|||
t.Errorf("Expected customFields are added")
|
||||
}
|
||||
})
|
||||
t.Run("Get CustomFields from Telegram", func(t *testing.T) {
|
||||
clients := factory.TelegramClients(config.Telegram{TargetBaseOptions: config.TargetBaseOptions{CustomFields: map[string]string{"field": "value"}}, Token: "XXX", ChatID: "1234"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
||||
client := reflect.ValueOf(clients[0]).Elem()
|
||||
|
||||
customFields := client.FieldByName("customFields").MapKeys()
|
||||
if customFields[0].String() != "field" {
|
||||
t.Errorf("Expected customFields are added")
|
||||
}
|
||||
})
|
||||
t.Run("Get CustomFields from Kinesis", func(t *testing.T) {
|
||||
clients := factory.KinesisClients(testConfig.Kinesis)
|
||||
if len(clients) < 1 {
|
||||
|
@ -612,6 +650,20 @@ func Test_GetValuesFromMountedSecret(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("Get Telegram Token from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.TelegramClients(config.Telegram{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, ChatID: "123"})
|
||||
if len(clients) != 1 {
|
||||
t.Error("Expected one client created")
|
||||
}
|
||||
|
||||
client := reflect.ValueOf(clients[0]).Elem()
|
||||
|
||||
token := client.FieldByName("host").String()
|
||||
if token != "http://localhost:9200/bottoken/sendMessage" {
|
||||
t.Errorf("Expected token from mounted secret, got %s", token)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get S3 values from MountedSecret", func(t *testing.T) {
|
||||
clients := factory.S3Clients(config.S3{TargetBaseOptions: config.TargetBaseOptions{MountedSecret: mountedSecret}, AWSConfig: config.AWSConfig{Endpoint: "endpoint", Region: "region"}, Bucket: "bucket"})
|
||||
if len(clients) != 1 {
|
||||
|
|
165
pkg/target/telegram/telegram.go
Normal file
165
pkg/target/telegram/telegram.go
Normal file
|
@ -0,0 +1,165 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/kyverno/policy-reporter/pkg/crd/api/policyreport/v1alpha2"
|
||||
"github.com/kyverno/policy-reporter/pkg/target"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/http"
|
||||
)
|
||||
|
||||
var replacer = strings.NewReplacer(
|
||||
"_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(",
|
||||
"\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>",
|
||||
"#", "\\#", "+", "\\+", "-", "\\-", "=", "\\=", "|",
|
||||
"\\|", "{", "\\{", "}", "\\}", ".", "\\.", "!", "\\!",
|
||||
)
|
||||
|
||||
func escape(text interface{}) string {
|
||||
return replacer.Replace(fmt.Sprintf("%v", text))
|
||||
}
|
||||
|
||||
var (
|
||||
notificationTempl = `*\[Policy Reporter\] \[{{ .Priority }}\] {{ escape (or .Result.Policy .Result.Rule) }}*
|
||||
{{- if .Resource }}
|
||||
|
||||
*Resource*: {{ .Resource.Kind }} {{ if .Resource.Namespace }}{{ escape .Resource.Namespace }}/{{ end }}{{ escape .Resource.Name }}
|
||||
|
||||
{{- end }}
|
||||
|
||||
*Status*: {{ escape .Result.Result }}
|
||||
*Time*: {{ escape (.Time.Format "02 Jan 06 15:04 MST") }}
|
||||
|
||||
{{ if .Result.Category }}*Category*: {{ escape .Result.Category }}{{ end }}
|
||||
{{ if .Result.Policy }}*Rule*: {{ escape .Result.Rule }}{{ end }}
|
||||
*Source*: {{ escape .Result.Source }}
|
||||
|
||||
*Message*:
|
||||
|
||||
{{ escape .Result.Message }}
|
||||
|
||||
*Properties*:
|
||||
{{ range $key, $value := .Result.Properties }}• *{{ escape $key }}*: {{ escape $value }}
|
||||
{{ end }}
|
||||
`
|
||||
)
|
||||
|
||||
type Payload struct {
|
||||
Text string `json:"text,omitempty"`
|
||||
ParseMode string `json:"parse_mode,omitempty"`
|
||||
DisableWebPagePreview bool `json:"disable_web_page_preview,omitempty"`
|
||||
ChatID string `json:"chat_id,omitempty"`
|
||||
}
|
||||
|
||||
type values struct {
|
||||
Result v1alpha2.PolicyReportResult
|
||||
Time time.Time
|
||||
Resource *corev1.ObjectReference
|
||||
Props map[string]string
|
||||
Priority string
|
||||
}
|
||||
|
||||
// Options to configure the Discord target
|
||||
type Options struct {
|
||||
target.ClientOptions
|
||||
ChatID string
|
||||
Host string
|
||||
Headers map[string]string
|
||||
CustomFields map[string]string
|
||||
HTTPClient http.Client
|
||||
}
|
||||
|
||||
type client struct {
|
||||
target.BaseClient
|
||||
chatID string
|
||||
host string
|
||||
headers map[string]string
|
||||
customFields map[string]string
|
||||
client http.Client
|
||||
}
|
||||
|
||||
func (e *client) Send(result v1alpha2.PolicyReportResult) {
|
||||
if len(e.customFields) > 0 {
|
||||
props := make(map[string]string, 0)
|
||||
|
||||
for property, value := range e.customFields {
|
||||
props[property] = value
|
||||
}
|
||||
|
||||
for property, value := range result.Properties {
|
||||
props[property] = value
|
||||
}
|
||||
|
||||
result.Properties = props
|
||||
}
|
||||
|
||||
payload := Payload{
|
||||
ParseMode: "MarkdownV2",
|
||||
DisableWebPagePreview: true,
|
||||
ChatID: e.chatID,
|
||||
}
|
||||
|
||||
var textBuffer bytes.Buffer
|
||||
|
||||
ttmpl, err := template.New("telegram").Funcs(template.FuncMap{"escape": escape}).Parse(notificationTempl)
|
||||
if err != nil {
|
||||
zap.L().Error(e.Name()+": PUSH FAILED", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
var res *corev1.ObjectReference
|
||||
if result.HasResource() {
|
||||
res = result.GetResource()
|
||||
}
|
||||
|
||||
var prio = result.Priority.String()
|
||||
if prio == "" {
|
||||
prio = v1alpha2.DebugPriority.String()
|
||||
}
|
||||
|
||||
err = ttmpl.Execute(&textBuffer, values{
|
||||
Result: result,
|
||||
Time: time.Now(),
|
||||
Resource: res,
|
||||
Priority: prio,
|
||||
})
|
||||
if err != nil {
|
||||
zap.L().Error(e.Name()+": PUSH FAILED", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
payload.Text = textBuffer.String()
|
||||
|
||||
req, err := http.CreateJSONRequest(e.Name(), "POST", e.host, payload)
|
||||
if err != nil {
|
||||
zap.L().Error(e.Name()+": PUSH FAILED", zap.Error(err))
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
for header, value := range e.headers {
|
||||
req.Header.Set(header, value)
|
||||
}
|
||||
|
||||
resp, err := e.client.Do(req)
|
||||
http.ProcessHTTPResponse(e.Name(), resp, err)
|
||||
}
|
||||
|
||||
// NewClient creates a new loki.client to send Results to Elasticsearch
|
||||
func NewClient(options Options) target.Client {
|
||||
return &client{
|
||||
target.NewBaseClient(options.ClientOptions),
|
||||
options.ChatID,
|
||||
options.Host,
|
||||
options.Headers,
|
||||
options.CustomFields,
|
||||
options.HTTPClient,
|
||||
}
|
||||
}
|
79
pkg/target/telegram/telegram_test.go
Normal file
79
pkg/target/telegram/telegram_test.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package telegram_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/policy-reporter/pkg/fixtures"
|
||||
"github.com/kyverno/policy-reporter/pkg/target"
|
||||
"github.com/kyverno/policy-reporter/pkg/target/telegram"
|
||||
)
|
||||
|
||||
type testClient struct {
|
||||
callback func(req *http.Request) error
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (c testClient) Do(req *http.Request) (*http.Response, error) {
|
||||
err := c.callback(req)
|
||||
|
||||
return &http.Response{
|
||||
StatusCode: c.statusCode,
|
||||
Body: io.NopCloser(strings.NewReader("")),
|
||||
}, err
|
||||
}
|
||||
|
||||
func Test_TelegramTarget(t *testing.T) {
|
||||
t.Run("Send", func(t *testing.T) {
|
||||
callback := func(req *http.Request) error {
|
||||
if contentType := req.Header.Get("Content-Type"); contentType != "application/json; charset=utf-8" {
|
||||
t.Errorf("Unexpected Content-Type: %s", contentType)
|
||||
}
|
||||
|
||||
if agend := req.Header.Get("User-Agent"); agend != "Policy-Reporter" {
|
||||
t.Errorf("Unexpected Host: %s", agend)
|
||||
}
|
||||
|
||||
if url := req.URL.String(); url != "https://api.telegram.org/botXXX/sendMessage" {
|
||||
t.Errorf("Unexpected Host: %s", url)
|
||||
}
|
||||
|
||||
if value := req.Header.Get("X-Code"); value != "1234" {
|
||||
t.Errorf("Unexpected Header X-Code: %s", value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
client := telegram.NewClient(telegram.Options{
|
||||
ClientOptions: target.ClientOptions{
|
||||
Name: "Telegram",
|
||||
},
|
||||
Host: "https://api.telegram.org/botXXX/sendMessage",
|
||||
Headers: map[string]string{"X-Code": "1234"},
|
||||
CustomFields: map[string]string{"cluster": "name"},
|
||||
HTTPClient: testClient{callback, 200},
|
||||
})
|
||||
client.Send(fixtures.CompleteTargetSendResult)
|
||||
|
||||
if len(fixtures.CompleteTargetSendResult.Properties) > 1 || fixtures.CompleteTargetSendResult.Properties["cluster"] != "" {
|
||||
t.Error("expected customFields are not added to the actuel result")
|
||||
}
|
||||
})
|
||||
t.Run("Name", func(t *testing.T) {
|
||||
client := telegram.NewClient(telegram.Options{
|
||||
ClientOptions: target.ClientOptions{
|
||||
Name: "Telegram",
|
||||
},
|
||||
Host: "https://api.telegram.org/botXXX/sendMessage",
|
||||
Headers: map[string]string{"X-Code": "1234"},
|
||||
HTTPClient: testClient{},
|
||||
})
|
||||
|
||||
if client.Name() != "Telegram" {
|
||||
t.Errorf("Unexpected Name %s", client.Name())
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue