From 70f939558ad6872698d78f20d7c4760442753892 Mon Sep 17 00:00:00 2001 From: michaeljguarino Date: Mon, 24 Jun 2024 18:33:47 -0400 Subject: [PATCH] Proper generation of ext urls (#521) When a user wants to split the graph between public/private, we're too blase about generating urls. This is a bit more precise and ensures the agent is configured correctly from the cli. --- cmd/plural/cd_clusters.go | 14 ++++++++-- go.mod | 2 +- go.sum | 2 ++ pkg/console/clusters.go | 13 ++++++++++ pkg/console/console.go | 22 ++++++++++++++++ pkg/test/mocks/ConsoleClient.go | 46 +++++++++++++++++++++++++++++++++ 6 files changed, 96 insertions(+), 3 deletions(-) diff --git a/cmd/plural/cd_clusters.go b/cmd/plural/cd_clusters.go index eda487e2..d4b7710d 100644 --- a/cmd/plural/cd_clusters.go +++ b/cmd/plural/cd_clusters.go @@ -401,7 +401,13 @@ func (p *Plural) reinstallOperator(c *cli.Context, id, handle *string) error { return err } - url := fmt.Sprintf("%s/ext/gql", p.ConsoleClient.Url()) + url := p.ConsoleClient.ExtUrl() + if cluster, err := p.ConsoleClient.GetCluster(id, handle); err == nil { + if agentUrl, err := p.ConsoleClient.AgentUrl(cluster.ID); err == nil { + url = agentUrl + } + } + return p.doInstallOperator(url, deployToken, c.String("values")) } @@ -446,8 +452,12 @@ func (p *Plural) handleClusterBootstrap(c *cli.Context) error { return fmt.Errorf("could not fetch deploy token from cluster") } + url := p.ConsoleClient.ExtUrl() + if agentUrl, err := p.ConsoleClient.AgentUrl(existing.CreateCluster.ID); err == nil { + url = agentUrl + } + deployToken := *existing.CreateCluster.DeployToken - url := fmt.Sprintf("%s/ext/gql", p.ConsoleClient.Url()) utils.Highlight("installing agent on %s with url %s and initial deploy token %s\n", c.String("name"), p.ConsoleClient.Url(), deployToken) return p.doInstallOperator(url, deployToken, c.String("values")) } diff --git a/go.mod b/go.mod index 06bc0694..19f8b20a 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/packethost/packngo v0.29.0 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/pluralsh/cluster-api-migration v0.2.16 - github.com/pluralsh/console-client-go v0.9.0 + github.com/pluralsh/console-client-go v0.9.1 github.com/pluralsh/gqlclient v1.11.0 github.com/pluralsh/plural-operator v0.5.5 github.com/pluralsh/polly v0.1.8 diff --git a/go.sum b/go.sum index c56f8370..35f0677c 100644 --- a/go.sum +++ b/go.sum @@ -1885,6 +1885,8 @@ github.com/pluralsh/cluster-api-migration v0.2.16 h1:MQGrLQAhGSSpyjEDamhnJZaQ8Mk github.com/pluralsh/cluster-api-migration v0.2.16/go.mod h1:24PjMsYv3vSlUiYw7BeUQ0GAtK0Jk2B1iwh35WGQLx8= github.com/pluralsh/console-client-go v0.9.0 h1:2rCPLVeooSV6WKfIKxqssloE1e6AkdP6LWwueQQlBsg= github.com/pluralsh/console-client-go v0.9.0/go.mod h1:eyCiLA44YbXiYyJh8303jk5JdPkt9McgCo5kBjk4lKo= +github.com/pluralsh/console-client-go v0.9.1 h1:o2khvyRu/d3ndehbX02CjnMbU6i0smhulhe0OYnp8yE= +github.com/pluralsh/console-client-go v0.9.1/go.mod h1:eyCiLA44YbXiYyJh8303jk5JdPkt9McgCo5kBjk4lKo= github.com/pluralsh/controller-reconcile-helper v0.0.4 h1:1o+7qYSyoeqKFjx+WgQTxDz4Q2VMpzprJIIKShxqG0E= github.com/pluralsh/controller-reconcile-helper v0.0.4/go.mod h1:AfY0gtteD6veBjmB6jiRx/aR4yevEf6K0M13/pGan/s= github.com/pluralsh/gqlclient v1.11.0 h1:FfXW7FiEJLHOfTAa7NxDb8jb3aMZNIpCAcG+bg8uHYA= diff --git a/pkg/console/clusters.go b/pkg/console/clusters.go index 767a8f6e..419acee2 100644 --- a/pkg/console/clusters.go +++ b/pkg/console/clusters.go @@ -37,6 +37,19 @@ func (c *consoleClient) GetCluster(clusterId, clusterName *string) (*consoleclie return result.Cluster, nil } +func (c *consoleClient) AgentUrl(id string) (string, error) { + res, err := c.client.GetAgentURL(c.ctx, id) + if err != nil { + return "", err + } + + if res == nil { + return "", fmt.Errorf("cluster not found") + } + + return lo.FromPtr(res.Cluster.AgentURL), nil +} + func (c *consoleClient) GetDeployToken(clusterId, clusterName *string) (string, error) { res, err := c.client.GetClusterWithToken(c.ctx, clusterId, clusterName) if err != nil { diff --git a/pkg/console/console.go b/pkg/console/console.go index c40a98cd..2827eb7c 100644 --- a/pkg/console/console.go +++ b/pkg/console/console.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "net/url" "strings" consoleclient "github.com/pluralsh/console-client-go" @@ -13,12 +14,15 @@ type consoleClient struct { ctx context.Context client consoleclient.ConsoleClient url string + extUrl string token string } type ConsoleClient interface { Url() string + ExtUrl() string Token() string + AgentUrl(id string) (string, error) ListClusters() (*consoleclient.ListClusters, error) GetCluster(clusterId, clusterName *string) (*consoleclient.ClusterFragment, error) GetDeployToken(clusterId, clusterName *string) (string, error) @@ -71,12 +75,26 @@ func NewConsoleClient(token, url string) (ConsoleClient, error) { return &consoleClient{ url: url, + extUrl: NormalizeExtUrl(url), token: token, client: consoleclient.NewClient(&httpClient, NormalizeUrl(url), nil), ctx: context.Background(), }, nil } +func NormalizeExtUrl(uri string) string { + if !strings.HasPrefix(uri, "https://") { + uri = fmt.Sprintf("https://%s", uri) + } + + parsed, err := url.Parse(uri) + if err != nil { + panic(err) + } + + return fmt.Sprintf("https://%s/ext/gql", parsed.Host) +} + func NormalizeUrl(url string) string { if !strings.HasPrefix(url, "https://") { url = fmt.Sprintf("https://%s", url) @@ -92,6 +110,10 @@ func (c *consoleClient) Url() string { return c.url } +func (c *consoleClient) ExtUrl() string { + return c.extUrl +} + func (c *consoleClient) Token() string { return c.token } diff --git a/pkg/test/mocks/ConsoleClient.go b/pkg/test/mocks/ConsoleClient.go index d098616c..bcc56623 100644 --- a/pkg/test/mocks/ConsoleClient.go +++ b/pkg/test/mocks/ConsoleClient.go @@ -12,6 +12,34 @@ type ConsoleClient struct { mock.Mock } +// AgentUrl provides a mock function with given fields: id +func (_m *ConsoleClient) AgentUrl(id string) (string, error) { + ret := _m.Called(id) + + if len(ret) == 0 { + panic("no return value specified for AgentUrl") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(string) (string, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(string) string); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CloneService provides a mock function with given fields: clusterId, serviceId, serviceName, clusterName, attributes func (_m *ConsoleClient) CloneService(clusterId string, serviceId *string, serviceName *string, clusterName *string, attributes gqlclient.ServiceCloneAttributes) (*gqlclient.ServiceDeploymentFragment, error) { ret := _m.Called(clusterId, serviceId, serviceName, clusterName, attributes) @@ -318,6 +346,24 @@ func (_m *ConsoleClient) DetachCluster(id string) error { return r0 } +// ExtUrl provides a mock function with given fields: +func (_m *ConsoleClient) ExtUrl() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for ExtUrl") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + // GetCluster provides a mock function with given fields: clusterId, clusterName func (_m *ConsoleClient) GetCluster(clusterId *string, clusterName *string) (*gqlclient.ClusterFragment, error) { ret := _m.Called(clusterId, clusterName)