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

Pass user token to API when creating/deleting CAPI clusters #965

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 22 additions & 9 deletions cmd/gitops/add/clusters/cmd.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package clusters

import (
"errors"
"fmt"
"os"
"strings"

"github.com/go-resty/resty/v2"
"github.com/spf13/cobra"
"github.com/weaveworks/weave-gitops/pkg/adapters"
"github.com/weaveworks/weave-gitops/pkg/apputils"
"github.com/weaveworks/weave-gitops/pkg/capi"
)

Expand Down Expand Up @@ -82,16 +85,26 @@ func getClusterCmdRunE(endpoint *string, client *resty.Client) func(*cobra.Comma
return capi.RenderTemplateWithParameters(flags.Template, vals, creds, r, os.Stdout)
}

if flags.RepositoryURL == "" {
return errors.New("repository url is required")
}

token, err := apputils.GetTokenForRepositoryURL(flags.RepositoryURL)
if err != nil {
return fmt.Errorf("failed to get token for git repository %q: %w", flags.RepositoryURL, err)
}

params := capi.CreatePullRequestFromTemplateParams{
TemplateName: flags.Template,
ParameterValues: vals,
RepositoryURL: flags.RepositoryURL,
HeadBranch: flags.HeadBranch,
BaseBranch: flags.BaseBranch,
Title: flags.Title,
Description: flags.Description,
CommitMessage: flags.CommitMessage,
Credentials: creds,
GitProviderToken: token,
TemplateName: flags.Template,
ParameterValues: vals,
RepositoryURL: flags.RepositoryURL,
HeadBranch: flags.HeadBranch,
BaseBranch: flags.BaseBranch,
Title: flags.Title,
Description: flags.Description,
CommitMessage: flags.CommitMessage,
Credentials: creds,
}

return capi.CreatePullRequestFromTemplate(params, r, os.Stdout)
Expand Down
24 changes: 24 additions & 0 deletions cmd/gitops/add/clusters/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package clusters_test

import (
"errors"
"strings"
"testing"

"github.com/go-resty/resty/v2"
"github.com/jarcoal/httpmock"
"github.com/weaveworks/weave-gitops/cmd/gitops/add/clusters"
)

func TestClusterCommand_URL(t *testing.T) {
e := "http://localhost"
client := resty.New()
httpmock.ActivateNonDefault(client.GetClient())
cmd := clusters.ClusterCommand(&e, client)
actual := cmd.Execute()
expected := errors.New("repository url is required")

if actual == nil || !strings.Contains(actual.Error(), expected.Error()) {
t.Fatalf("expected %q but got %q", expected, actual)
}
}
27 changes: 20 additions & 7 deletions cmd/gitops/delete/clusters/cmd.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package clusters

import (
"errors"
"fmt"
"os"

"github.com/go-resty/resty/v2"
"github.com/spf13/cobra"
"github.com/weaveworks/weave-gitops/pkg/adapters"
"github.com/weaveworks/weave-gitops/pkg/apputils"
"github.com/weaveworks/weave-gitops/pkg/clusters"
)

Expand Down Expand Up @@ -51,14 +54,24 @@ func deleteClusterCmdRunE(endpoint *string, client *resty.Client) func(*cobra.Co
return err
}

if clustersDeleteCmdFlags.RepositoryURL == "" {
return errors.New("repository url is required")
}

token, err := apputils.GetTokenForRepositoryURL(clustersDeleteCmdFlags.RepositoryURL)
yiannistri marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return fmt.Errorf("failed to get token for git repository %q: %w", clustersDeleteCmdFlags.RepositoryURL, err)
}

return clusters.DeleteClusters(clusters.DeleteClustersParams{
RepositoryURL: clustersDeleteCmdFlags.RepositoryURL,
HeadBranch: clustersDeleteCmdFlags.HeadBranch,
BaseBranch: clustersDeleteCmdFlags.BaseBranch,
Title: clustersDeleteCmdFlags.Title,
Description: clustersDeleteCmdFlags.Description,
ClustersNames: args,
CommitMessage: clustersDeleteCmdFlags.CommitMessage,
GitProviderToken: token,
RepositoryURL: clustersDeleteCmdFlags.RepositoryURL,
HeadBranch: clustersDeleteCmdFlags.HeadBranch,
BaseBranch: clustersDeleteCmdFlags.BaseBranch,
Title: clustersDeleteCmdFlags.Title,
Description: clustersDeleteCmdFlags.Description,
ClustersNames: args,
CommitMessage: clustersDeleteCmdFlags.CommitMessage,
}, r, os.Stdout)
}
}
25 changes: 25 additions & 0 deletions cmd/gitops/delete/clusters/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package clusters_test

import (
"errors"
"strings"
"testing"

"github.com/go-resty/resty/v2"
"github.com/jarcoal/httpmock"
"github.com/weaveworks/weave-gitops/cmd/gitops/delete/clusters"
)

func TestClusterCommand_URL(t *testing.T) {
e := "http://localhost"
client := resty.New()
httpmock.ActivateNonDefault(client.GetClient())
cmd := clusters.ClusterCommand(&e, client)
cmd.SetArgs([]string{"cluster-name"})
actual := cmd.Execute()
expected := errors.New("repository url is required")

if actual == nil || !strings.Contains(actual.Error(), expected.Error()) {
t.Fatalf("expected %q but got %q", expected, actual)
}
}
2 changes: 2 additions & 0 deletions pkg/adapters/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ func (c *HTTPClient) CreatePullRequestFromTemplate(params capi.CreatePullRequest

res, err := c.client.R().
SetHeader("Accept", "application/json").
SetHeader("Git-Provider-Token", params.GitProviderToken).
yiannistri marked this conversation as resolved.
Show resolved Hide resolved
SetBody(CreatePullRequestFromTemplateRequest{
RepositoryURL: params.RepositoryURL,
HeadBranch: params.HeadBranch,
Expand Down Expand Up @@ -442,6 +443,7 @@ func (c *HTTPClient) DeleteClusters(params clusters.DeleteClustersParams) (strin

res, err := c.client.R().
SetHeader("Accept", "application/json").
SetHeader("Git-Provider-Token", params.GitProviderToken).
SetBody(DeleteClustersPullRequestRequest{
HeadBranch: params.HeadBranch,
BaseBranch: params.BaseBranch,
Expand Down
26 changes: 26 additions & 0 deletions pkg/apputils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,29 @@ func GetAuthService(ctx context.Context, normalizedUrl gitproviders.RepoURL, dry

return auth.NewAuthService(fluxClient, rawClient, gitProvider, logger)
}

// GetTokenForRepositoryURL returns a token that is used to authenticate with
// a git provider.
func GetTokenForRepositoryURL(repoURL string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func GetTokenForRepositoryURL(repoURL string) (string, error) {
func GetTokenForRepositoryURL(provider string) (string, error) {

clients, err := GetBaseClients()
if err != nil {
return "", err
}

normalizedURL, err := gitproviders.NewRepoURL(repoURL)
if err != nil {
return "", fmt.Errorf("failed to normalize URL %q: %w", repoURL, err)
}

authHandler, err := auth.NewAuthCLIHandler(normalizedURL.Provider())
if err != nil {
return "", fmt.Errorf("error initializing cli auth handler: %w", err)
}

token, err := auth.GetToken(normalizedURL, clients.Osys, clients.Logger, authHandler)
if err != nil {
return "", fmt.Errorf("failed to get git provider token: %w", err)
}

return token, nil
}
19 changes: 10 additions & 9 deletions pkg/capi/capi.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,16 @@ type Credentials struct {
}

type CreatePullRequestFromTemplateParams struct {
TemplateName string
ParameterValues map[string]string
RepositoryURL string
HeadBranch string
BaseBranch string
Title string
Description string
CommitMessage string
Credentials Credentials
GitProviderToken string
TemplateName string
ParameterValues map[string]string
RepositoryURL string
HeadBranch string
BaseBranch string
Title string
Description string
CommitMessage string
Credentials Credentials
}

// GetTemplates uses a TemplatesRetriever adapter to show
Expand Down
15 changes: 8 additions & 7 deletions pkg/clusters/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,12 @@ func DeleteClusters(params DeleteClustersParams, r ClustersRetriever, w io.Write
}

type DeleteClustersParams struct {
RepositoryURL string
HeadBranch string
BaseBranch string
Title string
Description string
ClustersNames []string
CommitMessage string
GitProviderToken string
RepositoryURL string
HeadBranch string
BaseBranch string
Title string
Description string
ClustersNames []string
CommitMessage string
}
28 changes: 19 additions & 9 deletions pkg/services/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,26 @@ func NewAuthCLIHandler(name gitproviders.GitProviderName) (BlockingCLIAuthHandle
// InitGitProvider returns a GitProvider containing either the token stored in the <git provider>_TOKEN env var
// or a token retrieved via the CLI auth flow
func InitGitProvider(repoUrl gitproviders.RepoURL, osysClient osys.Osys, logger logger.Logger, cliAuthHandler BlockingCLIAuthHandler, getAccountType gitproviders.AccountTypeGetter) (gitproviders.GitProvider, error) {
token, err := GetToken(repoUrl, osysClient, logger, cliAuthHandler)
if err != nil {
return nil, fmt.Errorf("error getting git provider token: %w", err)
}

provider, err := gitproviders.New(gitproviders.Config{Provider: repoUrl.Provider(), Token: token}, repoUrl.Owner(), getAccountType)
if err != nil {
return nil, fmt.Errorf("error creating git provider client: %w", err)
}

return provider, nil
}

// GetToken returns a token that is used to authenticate with a git provider.
func GetToken(repoUrl gitproviders.RepoURL, osysClient osys.Osys, logger logger.Logger, cliAuthHandler BlockingCLIAuthHandler) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
func GetToken(repoUrl gitproviders.RepoURL, osysClient osys.Osys, logger logger.Logger, cliAuthHandler BlockingCLIAuthHandler) (string, error) {
func GetToken(provider string, osysClient osys.Osys, logger logger.Logger, cliAuthHandler BlockingCLIAuthHandler) (string, error) {

ctx := context.Background()

tokenVarName, err := getTokenVarName(repoUrl.Provider())
if err != nil {
return nil, fmt.Errorf("could not determine git provider token name: %w", err)
return "", fmt.Errorf("could not determine git provider token name: %w", err)
}

token, err := osysClient.GetGitProviderToken(tokenVarName)
Expand All @@ -59,21 +74,16 @@ func InitGitProvider(repoUrl gitproviders.RepoURL, osysClient osys.Osys, logger

generatedToken, err := cliAuthHandler(ctx, osysClient.Stdout())
if err != nil {
return nil, fmt.Errorf("could not complete auth flow: %w", err)
return "", fmt.Errorf("could not complete auth flow: %w", err)
}

token = generatedToken
} else if err != nil {
// We didn't detect a NoGitProviderSet error, something else went wrong.
return nil, fmt.Errorf("could not get access token: %w", err)
}

provider, err := gitproviders.New(gitproviders.Config{Provider: repoUrl.Provider(), Token: token}, repoUrl.Owner(), getAccountType)
if err != nil {
return nil, fmt.Errorf("error creating git provider client: %w", err)
return "", fmt.Errorf("could not get access token: %w", err)
}

return provider, nil
return token, nil
}

type SecretName struct {
Expand Down