Skip to content

Commit 4549f76

Browse files
authored
Merge pull request #63 from redpanda-data/conn-improvements
[bug] Reuse and close connections per resource
2 parents dff67f2 + 6a5d24d commit 4549f76

19 files changed

+215
-420
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ require (
1414
github.com/hashicorp/terraform-plugin-go v0.21.0
1515
github.com/hashicorp/terraform-plugin-testing v1.6.0
1616
github.com/redpanda-data/redpanda/src/go/rpk v0.0.0-20240122210157-821bd6d1fd31
17-
golang.org/x/sync v0.6.0
1817
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe
1918
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe
2019
google.golang.org/grpc v1.61.0

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,6 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
488488
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
489489
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
490490
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
491-
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
492-
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
493491
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
494492
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
495493
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

redpanda/clients/controlplane.go

Lines changed: 0 additions & 60 deletions
This file was deleted.

redpanda/clients/dataplane.go

Lines changed: 0 additions & 73 deletions
This file was deleted.

redpanda/clients/clients.go renamed to redpanda/cloud/cloud.go

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
// Package clients provides the CloudV2 clients used by the Redpanda terraform
17-
// provider and the generated resources.
18-
package clients
16+
// Package cloud provides the methods to connect and talk to the Redpanda Cloud
17+
// public API.
18+
package cloud
1919

2020
import (
2121
"context"
@@ -36,15 +36,15 @@ import (
3636
"google.golang.org/grpc/metadata"
3737
)
3838

39-
// cloudEndpoint is a representation of a cloud V2 endpoint, containing the URLs
40-
// for authentication and the API URL.
41-
type cloudEndpoint struct {
42-
apiURL string // CloudV2 public API URL.
39+
// Endpoint is a representation of a cloud endpoint for a single environment. It
40+
// contains the URLs, audience for authentication and the API URL.
41+
type Endpoint struct {
42+
APIURL string // CloudV2 public API URL.
4343
authURL string // CloudV2 URL for authorization token exchange.
4444
audience string // CloudV2 audience used for token exchange.
4545
}
4646

47-
var cloudAuthEnvironments = map[string]cloudEndpoint{
47+
var endpoints = map[string]Endpoint{
4848
"dev": {
4949
"api.dev.cloud.redpanda.com:443",
5050
"https://dev-cloudv2.us.auth0.com/oauth/token",
@@ -62,33 +62,27 @@ var cloudAuthEnvironments = map[string]cloudEndpoint{
6262
},
6363
}
6464

65-
// ClientRequest are the client request credentials used to create a connection.
66-
type ClientRequest struct {
67-
ClientID string
68-
ClientSecret string
69-
// TODO: we can use this as the only source of truth for Client Credentials and Envs.
70-
}
71-
7265
type tokenResponse struct {
7366
AccessToken string `json:"access_token"`
7467
Scope string `json:"scope"`
7568
ExpiresIn int `json:"expires_in"`
7669
TokenType string `json:"token_type"`
7770
}
7871

79-
// requestTokenAndEnv requests a token.
80-
func requestTokenAndEnv(ctx context.Context, cloudEnv string, cr ClientRequest) (string, *cloudEndpoint, error) {
81-
if cr.ClientID == "" {
72+
// RequestTokenAndEnv requests an authentication token and return the Endpoint
73+
// for a given environment.
74+
func RequestTokenAndEnv(ctx context.Context, cloudEnv, clientID, clientSecret string) (string, *Endpoint, error) {
75+
if clientID == "" {
8276
return "", nil, fmt.Errorf("client_id is not set")
8377
}
84-
if cr.ClientSecret == "" {
78+
if clientSecret == "" {
8579
return "", nil, fmt.Errorf("client_secret is not set")
8680
}
87-
endpoint, found := cloudAuthEnvironments[cloudEnv]
81+
endpoint, found := endpoints[cloudEnv]
8882
if !found {
8983
return "", nil, fmt.Errorf("unable to find requested environment: %q", cloudEnv)
9084
}
91-
payload := fmt.Sprintf("grant_type=client_credentials&client_id=%s&client_secret=%s&audience=%s", cr.ClientID, cr.ClientSecret, endpoint.audience)
85+
payload := fmt.Sprintf("grant_type=client_credentials&client_id=%s&client_secret=%s&audience=%s", clientID, clientSecret, endpoint.audience)
9286
req, err := http.NewRequestWithContext(ctx, "POST", endpoint.authURL, strings.NewReader(payload))
9387
if err != nil {
9488
return "", nil, fmt.Errorf("unable to issue request to %v: %v", endpoint.authURL, err)
@@ -118,7 +112,9 @@ func requestTokenAndEnv(ctx context.Context, cloudEnv string, cr ClientRequest)
118112
return tokenContainer.AccessToken, &endpoint, nil
119113
}
120114

121-
func spawnConn(ctx context.Context, url string, authToken string) (*grpc.ClientConn, error) {
115+
// SpawnConn returns a grpc connection to the given URL, it adds a bearer token
116+
// to each request with the given 'authToken'.
117+
func SpawnConn(ctx context.Context, url string, authToken string) (*grpc.ClientConn, error) {
122118
return grpc.DialContext(
123119
ctx,
124120
url,

redpanda/config/config.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2024 Redpanda Data, Inc.
2+
//
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
// Package config contains the configuration structs to initialize our clients
17+
// and provider.
18+
package config
19+
20+
import "google.golang.org/grpc"
21+
22+
// Resource is the config used to pass data and dependencies to resource
23+
// implementations.
24+
type Resource struct {
25+
AuthToken string
26+
ClientID string
27+
ClientSecret string
28+
CloudEnv string
29+
ControlPlaneConnection *grpc.ClientConn
30+
}
31+
32+
// Datasource is the config used to pass data and dependencies to data source
33+
// implementations.
34+
type Datasource struct {
35+
AuthToken string
36+
ClientID string
37+
ClientSecret string
38+
CloudEnv string
39+
ControlPlaneConnection *grpc.ClientConn
40+
}
41+
42+
// TODO add cloud provider and region as values to persist

redpanda/redpanda.go

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@ import (
2626
"github.com/hashicorp/terraform-plugin-framework/provider"
2727
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
2828
"github.com/hashicorp/terraform-plugin-framework/resource"
29+
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/cloud"
30+
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/config"
2931
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/models"
3032
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/resources/acl"
3133
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/resources/cluster"
3234
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/resources/namespace"
3335
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/resources/network"
3436
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/resources/topic"
3537
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/resources/user"
36-
"github.com/redpanda-data/terraform-provider-redpanda/redpanda/utils"
38+
"google.golang.org/grpc"
3739
)
3840

3941
// Ensure provider defined types fully satisfy framework interfaces.
@@ -46,6 +48,8 @@ type Redpanda struct {
4648
cloudEnv string
4749
// version is the Redpanda terraform provider.
4850
version string
51+
// conn is the connection to the control plane API.
52+
conn *grpc.ClientConn
4953
}
5054

5155
const (
@@ -118,15 +122,33 @@ func (r *Redpanda) Configure(ctx context.Context, request provider.ConfigureRequ
118122
}
119123
// Clients are passed through to downstream resources through the response
120124
// struct.
121-
response.ResourceData = utils.ResourceData{
122-
ClientID: id,
123-
ClientSecret: sec,
124-
CloudEnv: r.cloudEnv,
125+
token, endpoint, err := cloud.RequestTokenAndEnv(ctx, r.cloudEnv, id, sec)
126+
if err != nil {
127+
response.Diagnostics.AddError("failed to authenticate with Redpanda API", err.Error())
128+
return
129+
}
130+
if r.conn == nil {
131+
conn, err := cloud.SpawnConn(ctx, endpoint.APIURL, token)
132+
if err != nil {
133+
response.Diagnostics.AddError("failed to open a connection with the Redpanda Cloud API", err.Error())
134+
return
135+
}
136+
r.conn = conn
137+
}
138+
139+
response.ResourceData = config.Resource{
140+
AuthToken: token,
141+
ClientID: id,
142+
ClientSecret: sec,
143+
CloudEnv: r.cloudEnv,
144+
ControlPlaneConnection: r.conn,
125145
}
126-
response.DataSourceData = utils.DatasourceData{
127-
ClientID: id,
128-
ClientSecret: sec,
129-
CloudEnv: r.cloudEnv,
146+
response.DataSourceData = config.Datasource{
147+
AuthToken: token,
148+
ClientID: id,
149+
ClientSecret: sec,
150+
CloudEnv: r.cloudEnv,
151+
ControlPlaneConnection: r.conn,
130152
}
131153
}
132154

0 commit comments

Comments
 (0)