Skip to content

Commit 41c40a4

Browse files
committed
Add tests for Bridge/PGO integration code that hits the Bridge API.
1 parent e8bcff1 commit 41c40a4

11 files changed

+2571
-223
lines changed

cmd/postgres-operator/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ func addControllersToManager(mgr manager.Manager, openshift bool, log logr.Logge
177177
}
178178

179179
if util.DefaultMutableFeatureGate.Enabled(util.CrunchyBridgeClusters) {
180-
constructor := func() *bridge.Client {
180+
constructor := func() bridge.ClientInterface {
181181
client := bridge.NewClient(os.Getenv("PGO_BRIDGE_URL"), versionString)
182182
client.Transport = otelTransportWrapper()(http.DefaultTransport)
183183
return client

internal/bridge/client.go

+75-42
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ const defaultAPI = "https://api.crunchybridge.com"
3838

3939
var errAuthentication = errors.New("authentication failed")
4040

41+
type ClientInterface interface {
42+
ListClusters(ctx context.Context, apiKey, teamId string) ([]*ClusterApiResource, error)
43+
CreateCluster(ctx context.Context, apiKey string, clusterRequestPayload *PostClustersRequestPayload) (*ClusterApiResource, error)
44+
DeleteCluster(ctx context.Context, apiKey, id string) (*ClusterApiResource, bool, error)
45+
GetCluster(ctx context.Context, apiKey, id string) (*ClusterApiResource, error)
46+
GetClusterStatus(ctx context.Context, apiKey, id string) (*ClusterStatusApiResource, error)
47+
GetClusterUpgrade(ctx context.Context, apiKey, id string) (*ClusterUpgradeApiResource, error)
48+
UpgradeCluster(ctx context.Context, apiKey, id string, clusterRequestPayload *PostClustersUpgradeRequestPayload) (*ClusterUpgradeApiResource, error)
49+
UpgradeClusterHA(ctx context.Context, apiKey, id, action string) (*ClusterUpgradeApiResource, error)
50+
UpdateCluster(ctx context.Context, apiKey, id string, clusterRequestPayload *PatchClustersRequestPayload) (*ClusterApiResource, error)
51+
GetClusterRole(ctx context.Context, apiKey, clusterId, roleName string) (*ClusterRoleApiResource, error)
52+
}
53+
4154
type Client struct {
4255
http.Client
4356
wait.Backoff
@@ -146,13 +159,30 @@ type ClusterUpgradeOperationApiResource struct {
146159
State string `json:"state,omitempty"`
147160
}
148161

162+
// ClusterRoleApiResource is used for retrieving details on ClusterRole from the Bridge API
163+
type ClusterRoleApiResource struct {
164+
AccountEmail string `json:"account_email"`
165+
AccountId string `json:"account_id"`
166+
ClusterId string `json:"cluster_id"`
167+
Flavor string `json:"flavor"`
168+
Name string `json:"name"`
169+
Password string `json:"password"`
170+
Team string `json:"team_id"`
171+
URI string `json:"uri"`
172+
}
173+
174+
// ClusterRoleList holds a slice of ClusterRoleApiResource
175+
type ClusterRoleList struct {
176+
Roles []*ClusterRoleApiResource `json:"roles"`
177+
}
178+
149179
// BRIDGE API REQUEST PAYLOADS
150180

151181
// PatchClustersRequestPayload is used for updating various properties of an existing cluster.
152182
type PatchClustersRequestPayload struct {
153183
ClusterGroup string `json:"cluster_group_id,omitempty"`
154184
// DashboardSettings *ClusterDashboardSettings `json:"dashboard_settings,omitempty"`
155-
// TODO: (dsessler7) Find docs for DashboardSettings and create appropriate struct
185+
// TODO(dsessler7): Find docs for DashboardSettings and create appropriate struct
156186
Environment string `json:"environment,omitempty"`
157187
IsProtected *bool `json:"is_protected,omitempty"`
158188
MaintenanceWindowStart int64 `json:"maintenance_window_start,omitempty"`
@@ -194,23 +224,6 @@ type PutClustersUpgradeRequestPayload struct {
194224
UseMaintenanceWindow *bool `json:"use_cluster_maintenance_window,omitempty"`
195225
}
196226

197-
// ClusterRoleApiResource is used for retrieving details on ClusterRole from the Bridge API
198-
type ClusterRoleApiResource struct {
199-
AccountEmail string `json:"account_email"`
200-
AccountId string `json:"account_id"`
201-
ClusterId string `json:"cluster_id"`
202-
Flavor string `json:"flavor"`
203-
Name string `json:"name"`
204-
Password string `json:"password"`
205-
Team string `json:"team_id"`
206-
URI string `json:"uri"`
207-
}
208-
209-
// ClusterRoleList holds a slice of ClusterRoleApiResource
210-
type ClusterRoleList struct {
211-
Roles []*ClusterRoleApiResource `json:"roles"`
212-
}
213-
214227
// BRIDGE CLIENT FUNCTIONS AND METHODS
215228

216229
// NewClient creates a Client with backoff settings that amount to
@@ -415,9 +428,10 @@ func (c *Client) CreateInstallation(ctx context.Context) (Installation, error) {
415428
return result, err
416429
}
417430

418-
// TODO(crunchybridgecluster) Is this where we want CRUD for clusters functions? Or make client `do` funcs
419-
// directly callable?
431+
// CRUNCHYBRIDGECLUSTER CRUD METHODS
420432

433+
// ListClusters makes a GET request to the "/clusters" endpoint to retrieve a list of all clusters
434+
// in Bridge that are owned by the team specified by the provided team id.
421435
func (c *Client) ListClusters(ctx context.Context, apiKey, teamId string) ([]*ClusterApiResource, error) {
422436
result := &ClusterList{}
423437

@@ -450,6 +464,8 @@ func (c *Client) ListClusters(ctx context.Context, apiKey, teamId string) ([]*Cl
450464
return result.Clusters, err
451465
}
452466

467+
// CreateCluster makes a POST request to the "/clusters" endpoint thereby creating a cluster
468+
// in Bridge with the settings specified in the request payload.
453469
func (c *Client) CreateCluster(
454470
ctx context.Context, apiKey string, clusterRequestPayload *PostClustersRequestPayload,
455471
) (*ClusterApiResource, error) {
@@ -534,6 +550,8 @@ func (c *Client) DeleteCluster(ctx context.Context, apiKey, id string) (*Cluster
534550
return result, deletedAlready, err
535551
}
536552

553+
// GetCluster makes a GET request to the "/clusters/<id>" endpoint, thereby retrieving details
554+
// for a given cluster in Bridge specified by the provided cluster id.
537555
func (c *Client) GetCluster(ctx context.Context, apiKey, id string) (*ClusterApiResource, error) {
538556
result := &ClusterApiResource{}
539557

@@ -566,6 +584,8 @@ func (c *Client) GetCluster(ctx context.Context, apiKey, id string) (*ClusterApi
566584
return result, err
567585
}
568586

587+
// GetClusterStatus makes a GET request to the "/clusters/<id>/status" endpoint, thereby retrieving details
588+
// for a given cluster's status in Bridge, specified by the provided cluster id.
569589
func (c *Client) GetClusterStatus(ctx context.Context, apiKey, id string) (*ClusterStatusApiResource, error) {
570590
result := &ClusterStatusApiResource{}
571591

@@ -598,6 +618,8 @@ func (c *Client) GetClusterStatus(ctx context.Context, apiKey, id string) (*Clus
598618
return result, err
599619
}
600620

621+
// GetClusterUpgrade makes a GET request to the "/clusters/<id>/upgrade" endpoint, thereby retrieving details
622+
// for a given cluster's upgrade status in Bridge, specified by the provided cluster id.
601623
func (c *Client) GetClusterUpgrade(ctx context.Context, apiKey, id string) (*ClusterUpgradeApiResource, error) {
602624
result := &ClusterUpgradeApiResource{}
603625

@@ -630,6 +652,8 @@ func (c *Client) GetClusterUpgrade(ctx context.Context, apiKey, id string) (*Clu
630652
return result, err
631653
}
632654

655+
// UpgradeCluster makes a POST request to the "/clusters/<id>/upgrade" endpoint, thereby attempting
656+
// to upgrade certain settings for a given cluster in Bridge.
633657
func (c *Client) UpgradeCluster(
634658
ctx context.Context, apiKey, id string, clusterRequestPayload *PostClustersUpgradeRequestPayload,
635659
) (*ClusterUpgradeApiResource, error) {
@@ -669,6 +693,9 @@ func (c *Client) UpgradeCluster(
669693
return result, err
670694
}
671695

696+
// UpgradeClusterHA makes a PUT request to the "/clusters/<id>/actions/<action>" endpoint,
697+
// where <action> is either "enable-ha" or "disable-ha", thereby attempting to change the
698+
// HA setting for a given cluster in Bridge.
672699
func (c *Client) UpgradeClusterHA(ctx context.Context, apiKey, id, action string) (*ClusterUpgradeApiResource, error) {
673700
result := &ClusterUpgradeApiResource{}
674701

@@ -701,10 +728,19 @@ func (c *Client) UpgradeClusterHA(ctx context.Context, apiKey, id, action string
701728
return result, err
702729
}
703730

704-
func (c *Client) GetClusterRole(ctx context.Context, apiKey, clusterId, roleName string) (*ClusterRoleApiResource, error) {
705-
result := &ClusterRoleApiResource{}
731+
// UpdateCluster makes a PATCH request to the "/clusters/<id>" endpoint, thereby attempting to
732+
// update certain settings for a given cluster in Bridge.
733+
func (c *Client) UpdateCluster(
734+
ctx context.Context, apiKey, id string, clusterRequestPayload *PatchClustersRequestPayload,
735+
) (*ClusterApiResource, error) {
736+
result := &ClusterApiResource{}
706737

707-
response, err := c.doWithRetry(ctx, "GET", "/clusters/"+clusterId+"/roles/"+roleName, nil, nil, http.Header{
738+
clusterbyte, err := json.Marshal(clusterRequestPayload)
739+
if err != nil {
740+
return result, err
741+
}
742+
743+
response, err := c.doWithRetry(ctx, "PATCH", "/clusters/"+id, nil, clusterbyte, http.Header{
708744
"Accept": []string{"application/json"},
709745
"Authorization": []string{"Bearer " + apiKey},
710746
})
@@ -718,6 +754,10 @@ func (c *Client) GetClusterRole(ctx context.Context, apiKey, clusterId, roleName
718754
case response.StatusCode >= 200 && response.StatusCode < 300:
719755
if err = json.Unmarshal(body, &result); err != nil {
720756
err = fmt.Errorf("%w: %s", err, body)
757+
return result, err
758+
}
759+
if err = json.Unmarshal(body, &result.ResponsePayload); err != nil {
760+
err = fmt.Errorf("%w: %s", err, body)
721761
}
722762

723763
default:
@@ -729,10 +769,12 @@ func (c *Client) GetClusterRole(ctx context.Context, apiKey, clusterId, roleName
729769
return result, err
730770
}
731771

732-
func (c *Client) ListClusterRoles(ctx context.Context, apiKey, id string) ([]*ClusterRoleApiResource, error) {
733-
result := ClusterRoleList{}
772+
// GetClusterRole sends a GET request to the "/clusters/<id>/roles/<roleName>" endpoint, thereby retrieving
773+
// Role information for a specific role from a specific cluster in Bridge.
774+
func (c *Client) GetClusterRole(ctx context.Context, apiKey, clusterId, roleName string) (*ClusterRoleApiResource, error) {
775+
result := &ClusterRoleApiResource{}
734776

735-
response, err := c.doWithRetry(ctx, "GET", "/clusters/"+id+"/roles", nil, nil, http.Header{
777+
response, err := c.doWithRetry(ctx, "GET", "/clusters/"+clusterId+"/roles/"+roleName, nil, nil, http.Header{
736778
"Accept": []string{"application/json"},
737779
"Authorization": []string{"Bearer " + apiKey},
738780
})
@@ -754,20 +796,15 @@ func (c *Client) ListClusterRoles(ctx context.Context, apiKey, id string) ([]*Cl
754796
}
755797
}
756798

757-
return result.Roles, err
799+
return result, err
758800
}
759801

760-
func (c *Client) UpdateCluster(
761-
ctx context.Context, apiKey, id string, clusterRequestPayload *PatchClustersRequestPayload,
762-
) (*ClusterApiResource, error) {
763-
result := &ClusterApiResource{}
764-
765-
clusterbyte, err := json.Marshal(clusterRequestPayload)
766-
if err != nil {
767-
return result, err
768-
}
802+
// ListClusterRoles sends a GET request to the "/clusters/<id>/roles" endpoint thereby retrieving
803+
// a list of all cluster roles for a specific cluster in Bridge.
804+
func (c *Client) ListClusterRoles(ctx context.Context, apiKey, id string) ([]*ClusterRoleApiResource, error) {
805+
result := ClusterRoleList{}
769806

770-
response, err := c.doWithRetry(ctx, "PATCH", "/clusters/"+id, nil, clusterbyte, http.Header{
807+
response, err := c.doWithRetry(ctx, "GET", "/clusters/"+id+"/roles", nil, nil, http.Header{
771808
"Accept": []string{"application/json"},
772809
"Authorization": []string{"Bearer " + apiKey},
773810
})
@@ -781,10 +818,6 @@ func (c *Client) UpdateCluster(
781818
case response.StatusCode >= 200 && response.StatusCode < 300:
782819
if err = json.Unmarshal(body, &result); err != nil {
783820
err = fmt.Errorf("%w: %s", err, body)
784-
return result, err
785-
}
786-
if err = json.Unmarshal(body, &result.ResponsePayload); err != nil {
787-
err = fmt.Errorf("%w: %s", err, body)
788821
}
789822

790823
default:
@@ -793,5 +826,5 @@ func (c *Client) UpdateCluster(
793826
}
794827
}
795828

796-
return result, err
829+
return result.Roles, err
797830
}

0 commit comments

Comments
 (0)