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

Remove ProviderBuilder #3282

Merged
merged 2 commits into from
May 8, 2024
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
34 changes: 9 additions & 25 deletions cmd/dev/app/container/cmd_verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,22 @@ package container

import (
"context"
"database/sql"
"encoding/json"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"

serverconfig "github.com/stacklok/minder/internal/config/server"
"github.com/stacklok/minder/internal/db"
"github.com/stacklok/minder/internal/providers"
"github.com/stacklok/minder/internal/providers/credentials"
"github.com/stacklok/minder/internal/providers/github/clients"
"github.com/stacklok/minder/internal/providers/ratecache"
"github.com/stacklok/minder/internal/providers/telemetry"
"github.com/stacklok/minder/internal/verifier"
"github.com/stacklok/minder/internal/verifier/sigstore"
"github.com/stacklok/minder/internal/verifier/sigstore/container"
"github.com/stacklok/minder/internal/verifier/verifyif"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
provifv1 "github.com/stacklok/minder/pkg/providers/v1"
)

Expand Down Expand Up @@ -110,26 +109,11 @@ func runCmdVerify(cmd *cobra.Command, _ []string) error {
}

func buildGitHubClient(token string) (provifv1.GitHub, error) {
pbuild := providers.NewProviderBuilder(
&db.Provider{
Name: "test",
Version: "v1",
Implements: []db.ProviderType{
"rest",
"git",
"github",
},
Definition: json.RawMessage(`{
"rest": {},
"github": {}
}`),
},
sql.NullString{},
false,
return clients.NewRestClient(
&minderv1.GitHubProviderConfig{},
&ratecache.NoopRestClientCache{},
credentials.NewGitHubTokenCredential(token),
&serverconfig.ProviderConfig{},
nil, // this is unused here
clients.NewGitHubClientFactory(telemetry.NewNoopMetrics()),
"",
)

return pbuild.GetGitHub()
}
133 changes: 91 additions & 42 deletions cmd/server/app/webhook_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ import (
"github.com/stacklok/minder/internal/logger"
"github.com/stacklok/minder/internal/providers"
ghprovider "github.com/stacklok/minder/internal/providers/github"
"github.com/stacklok/minder/internal/providers/github/clients"
ghmanager "github.com/stacklok/minder/internal/providers/github/manager"
"github.com/stacklok/minder/internal/providers/manager"
"github.com/stacklok/minder/internal/providers/ratecache"
"github.com/stacklok/minder/internal/providers/telemetry"
provifv1 "github.com/stacklok/minder/pkg/providers/v1"
)

Expand Down Expand Up @@ -69,23 +74,11 @@ func runCmdWebhookUpdate(cmd *cobra.Command, _ []string) error {

providerName := cmd.Flag("provider").Value.String()

cryptoEng, err := crypto.EngineFromAuthConfig(&cfg.Auth)
store, err := wireUpDB(ctx, cfg)
if err != nil {
return fmt.Errorf("failed to create crypto engine: %w", err)
return err
}

dbConn, _, err := cfg.Database.GetDBConnection(ctx)
if err != nil {
return fmt.Errorf("unable to connect to database: %w", err)
}
defer func(dbConn *sql.DB) {
err := dbConn.Close()
if err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("error closing database connection")
}
}(dbConn)

store := db.NewStore(dbConn)
allProviders, err := store.GlobalListProviders(ctx)
if err != nil {
return fmt.Errorf("unable to list providers: %w", err)
Expand All @@ -96,47 +89,54 @@ func runCmdWebhookUpdate(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("unable to parse webhook url: %w", err)
}

fallbackTokenClient := ghprovider.NewFallbackTokenClient(cfg.Provider)
whSecret, err := getWebhookSecret(cfg)
if err != nil {
return err
}

providerManager, err := wireUpProviderManager(cfg, store)
if err != nil {
return fmt.Errorf("failed to instantiate provider manager: %w", err)
}

for _, provider := range allProviders {
zerolog.Ctx(ctx).Info().Str("name", provider.Name).Str("uuid", provider.ID.String()).Msg("provider")
pb, err := providers.GetProviderBuilder(ctx, provider, store, cryptoEng, &cfg.Provider, fallbackTokenClient)
if err != nil {
return fmt.Errorf("unable to get provider builder: %w", err)
if providerName != "" && providerName != provider.Name {
continue
}

if !pb.Implements(db.ProviderType(providerName)) {
if !provider.CanImplement(db.ProviderTypeGithub) {
// currently we can only operate on GitHub
// revisit this once we add more providers with webhooks
zerolog.Ctx(ctx).Info().
Str("name", provider.Name).
Str("uuid", provider.ID.String()).
Msg("provider does not implement the requested provider interface")
continue
}

var updateErr error

if db.ProviderType(providerName) == db.ProviderTypeGithub {
ghCli, err := pb.GetGitHub()
if err != nil {
zerolog.Ctx(ctx).Err(err).Msg("cannot get github client")
continue
}

whSecret, err := cfg.WebhookConfig.GetWebhookSecret()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, this is constant across all iterations of the loop, so I moved it outside of the loop

if err != nil {
zerolog.Ctx(ctx).Err(err).Msg("cannot get webhook secret")
continue
}

if whSecret == "" {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is empty, no webhooks are updated, so I converted to an error condition (see line 263)

zerolog.Ctx(ctx).Error().Msg("webhook secret is empty")
continue
}
updateErr = updateGithubWebhooks(ctx, ghCli, store, provider, webhookUrl.Host, whSecret)
} else {
updateErr = fmt.Errorf("provider type %s not supported", providerName)
zerolog.Ctx(ctx).Info().
Str("name", provider.Name).
Str("uuid", provider.ID.String()).
Msg("provider")

// We end up querying each provider db record twice - once to build
// the slice which this loop iterates over, and a second time to
// instantiate the provider. Taking this approach since we plan on
// changing webhook handling in minder, so I do not want to create any
// throwaway code.
providerInstance, err := providerManager.InstantiateFromID(ctx, provider.ID)
if err != nil {
zerolog.Ctx(ctx).Err(err).Msg("cannot instantiate provider")
continue
}

ghCli, err := provifv1.As[provifv1.GitHub](providerInstance)
if err != nil {
zerolog.Ctx(ctx).Err(err).Msg("cannot convert to github provider")
continue
}

updateErr := updateGithubWebhooks(ctx, ghCli, store, provider, webhookUrl.Host, whSecret)
if updateErr != nil {
zerolog.Ctx(ctx).Err(updateErr).Msg("unable to update webhooks")
}
Expand Down Expand Up @@ -217,3 +217,52 @@ func updateGithubRepoHooks(

return nil
}

func wireUpProviderManager(cfg *serverconfig.Config, store db.Store) (manager.ProviderManager, error) {
cryptoEng, err := crypto.EngineFromAuthConfig(&cfg.Auth)
if err != nil {
return nil, fmt.Errorf("failed to create crypto engine: %w", err)
}
fallbackTokenClient := ghprovider.NewFallbackTokenClient(cfg.Provider)
providerStore := providers.NewProviderStore(store)
githubProviderManager := ghmanager.NewGitHubProviderClassManager(
&ratecache.NoopRestClientCache{},
clients.NewGitHubClientFactory(telemetry.NewNoopMetrics()),
&cfg.Provider,
fallbackTokenClient,
cryptoEng,
nil, // whManager not needed here (only when creating/delete webhooks)
store,
nil, // ghProviderService not needed here
)

return manager.NewProviderManager(providerStore, githubProviderManager)
}

func wireUpDB(ctx context.Context, cfg *serverconfig.Config) (db.Store, error) {
Copy link
Contributor Author

@dmjb dmjb May 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored some of this code into separate functions out to reduce cyclomatic complexity of the runCmdWebhookUpdate (the new code I added exceeded the cyclomatic complexity limit)

dbConn, _, err := cfg.Database.GetDBConnection(ctx)
if err != nil {
return nil, fmt.Errorf("unable to connect to database: %w", err)
}
defer func(dbConn *sql.DB) {
err := dbConn.Close()
if err != nil {
zerolog.Ctx(ctx).Error().Err(err).Msg("error closing database connection")
}
}(dbConn)

return db.NewStore(dbConn), nil
}

func getWebhookSecret(cfg *serverconfig.Config) (string, error) {
secret, err := cfg.WebhookConfig.GetWebhookSecret()
if err != nil {
return "", fmt.Errorf("cannot read secret from config: %w", err)
}

if secret == "" {
return "", fmt.Errorf("webhook secret is empty in config: %w", err)
}

return secret, nil
}
Loading