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

Add cloud teams integration #1298

Merged
merged 2 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions cmd/botkube-agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,14 @@ func run(ctx context.Context) (err error) {
scheduleBotNotifier(tb)
}

if commGroupCfg.CloudTeams.Enabled {
sb, err := bot.NewCloudTeams(commGroupLogger.WithField(botLogFieldKey, "CloudTeams"), commGroupMeta, commGroupCfg.CloudTeams, conf.Settings.ClusterName, executorFactory, reporter)
mszostok marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return reportFatalError("while creating CloudSlack bot", err)
}
scheduleBotNotifier(sb)
}

if commGroupCfg.Discord.Enabled {
db, err := bot.NewDiscord(commGroupLogger.WithField(botLogFieldKey, "Discord"), commGroupMeta, commGroupCfg.Discord, executorFactory, reporter)
if err != nil {
Expand Down
51 changes: 27 additions & 24 deletions internal/plugin/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ func NewCollector(log logrus.FieldLogger) *Collector {
return &Collector{log: log}
}

type botBindingsGetter interface {
config.Identifiable
GetBotBindings() config.BotBindings
}

func collect[T botBindingsGetter](boundExecutors, boundSources map[string]struct{}, channels config.IdentifiableMap[T]) {
for _, bindings := range channels {
for _, name := range bindings.GetBotBindings().Executors {
boundExecutors[name] = struct{}{}
}
for _, name := range bindings.GetBotBindings().Sources {
boundSources[name] = struct{}{}
}
}
}

// GetAllEnabledAndUsedPlugins returns the list of all plugins that are both enabled and bind to at
// least one communicator or action (automation) that is enabled.
func (c *Collector) GetAllEnabledAndUsedPlugins(cfg *config.Config) ([]string, []string) {
Expand All @@ -25,33 +41,21 @@ func (c *Collector) GetAllEnabledAndUsedPlugins(cfg *config.Config) ([]string, [
boundSources = map[string]struct{}{}
)

// Collect all used executors/sources by communication platforms
collect := func(channels config.IdentifiableMap[config.ChannelBindingsByName]) {
for _, bindings := range channels {
for _, name := range bindings.Bindings.Executors {
boundExecutors[name] = struct{}{}
}
for _, name := range bindings.Bindings.Sources {
boundSources[name] = struct{}{}
}
}
}

for _, commGroupCfg := range cfg.Communications {
if commGroupCfg.Slack.Enabled {
collect(commGroupCfg.Slack.Channels)
collect(boundExecutors, boundSources, commGroupCfg.Slack.Channels)
}

if commGroupCfg.SocketSlack.Enabled {
collect(commGroupCfg.SocketSlack.Channels)
collect(boundExecutors, boundSources, commGroupCfg.SocketSlack.Channels)
}

if commGroupCfg.CloudSlack.Enabled {
collect(commGroupCfg.CloudSlack.Channels)
collect(boundExecutors, boundSources, commGroupCfg.CloudSlack.Channels)
}

if commGroupCfg.Mattermost.Enabled {
collect(commGroupCfg.Mattermost.Channels)
collect(boundExecutors, boundSources, commGroupCfg.Mattermost.Channels)
}

if commGroupCfg.Teams.Enabled {
Expand All @@ -63,17 +67,16 @@ func (c *Collector) GetAllEnabledAndUsedPlugins(cfg *config.Config) ([]string, [
}
}

if commGroupCfg.Discord.Enabled {
for _, bindings := range commGroupCfg.Discord.Channels {
for _, name := range bindings.Bindings.Executors {
boundExecutors[name] = struct{}{}
}
for _, name := range bindings.Bindings.Sources {
boundSources[name] = struct{}{}
}
if commGroupCfg.CloudTeams.Enabled {
for _, team := range commGroupCfg.CloudTeams.Teams {
collect(boundExecutors, boundSources, team.Channels)
}
}

if commGroupCfg.Discord.Enabled {
collect(boundExecutors, boundSources, commGroupCfg.Discord.Channels)
}

if commGroupCfg.Webhook.Enabled {
for _, name := range commGroupCfg.Webhook.Bindings.Sources {
boundSources[name] = struct{}{}
Expand Down
9 changes: 9 additions & 0 deletions internal/source/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,15 @@ func (d *Scheduler) generateConfigs(ctx context.Context) error {
return err
}
}
if commGroupCfg.CloudTeams.Enabled {
for _, teams := range commGroupCfg.CloudTeams.Teams {
for _, channel := range teams.Channels {
if err := d.generateSourceConfigs(ctx, config.CloudTeamsCommPlatformIntegration.IsInteractive(), channel.Bindings.Sources); err != nil {
return err
}
}
}
}

if commGroupCfg.Discord.Enabled {
for _, channel := range commGroupCfg.Discord.Channels {
Expand Down
45 changes: 45 additions & 0 deletions pkg/api/cloudplatform/creds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cloudplatform

import (
"context"

"google.golang.org/grpc"
"google.golang.org/grpc/metadata"

"github.com/kubeshop/botkube/internal/config/remote"
)

const (
APIKeyContextKey = "X-Api-Key" // #nosec
DeploymentIDContextKey = "X-Deployment-Id" // #nosec
)

func AddStreamingClientCredentials(remoteCfg remote.Config) grpc.StreamClientInterceptor {
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
md := metadata.New(map[string]string{
APIKeyContextKey: remoteCfg.APIKey,
DeploymentIDContextKey: remoteCfg.Identifier,
})

ctx = metadata.NewOutgoingContext(ctx, md)

clientStream, err := streamer(ctx, desc, cc, method, opts...)
if err != nil {
return nil, err
}

return clientStream, nil
}
}

func AddUnaryClientCredentials(remoteCfg remote.Config) grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
md := metadata.New(map[string]string{
APIKeyContextKey: remoteCfg.APIKey,
DeploymentIDContextKey: remoteCfg.Identifier,
})

ctx = metadata.NewOutgoingContext(ctx, md)
return invoker(ctx, method, req, reply, cc, opts...)
}
}

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

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

Loading