Skip to content

Commit 8fa83ec

Browse files
omerdemirokactions-user
authored andcommitted
feat: add healthcheck adpater (#1454)
Resolves https://github.com/overmindtech/workspace/issues/1435 Features: Implements GCP HealthCheck adapter GitOrigin-RevId: 9037bddf22977f57bb783cd82dbc72e1458a9ced
1 parent 253330b commit 8fa83ec

File tree

8 files changed

+526
-1
lines changed

8 files changed

+526
-1
lines changed

sources/gcp/adapters/adapters.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ func Adapters(ctx context.Context, projectID string, regions []string, zones []s
4040
return nil, err
4141
}
4242

43+
computeHealthCheckCli, err := compute.NewHealthChecksRESTClient(ctx)
44+
if err != nil {
45+
return nil, err
46+
}
47+
4348
backendServiceCli, err := compute.NewBackendServicesRESTClient(ctx)
4449
if err != nil {
4550
return nil, err
@@ -77,6 +82,7 @@ func Adapters(ctx context.Context, projectID string, regions []string, zones []s
7782
adapters = append(adapters,
7883
sources.WrapperToAdapter(NewComputeBackendService(shared.NewComputeBackendServiceClient(backendServiceCli), projectID)),
7984
sources.WrapperToAdapter(NewComputeImage(shared.NewComputeImagesClient(computeImagesCli), projectID)),
85+
sources.WrapperToAdapter(NewComputeHealthCheck(shared.NewComputeHealthCheckClient(computeHealthCheckCli), projectID)),
8086
)
8187

8288
// Register the metadata for each adapter
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package adapters
2+
3+
import (
4+
"context"
5+
"errors"
6+
7+
"cloud.google.com/go/compute/apiv1/computepb"
8+
"google.golang.org/api/iterator"
9+
10+
"github.com/overmindtech/cli/sdp-go"
11+
"github.com/overmindtech/cli/sources"
12+
gcpshared "github.com/overmindtech/cli/sources/gcp/shared"
13+
"github.com/overmindtech/cli/sources/shared"
14+
)
15+
16+
var (
17+
ComputeHealthCheck = shared.NewItemType(gcpshared.GCP, gcpshared.Compute, gcpshared.HealthCheck)
18+
19+
ComputeHealthCheckLookupByName = shared.NewItemTypeLookup("name", ComputeHealthCheck)
20+
)
21+
22+
type computeHealthCheckWrapper struct {
23+
client gcpshared.ComputeHealthCheckClient
24+
25+
*gcpshared.ProjectBase
26+
}
27+
28+
// NewComputeHealthCheck creates a new computeHealthCheckWrapper instance.
29+
func NewComputeHealthCheck(client gcpshared.ComputeHealthCheckClient, projectID string) sources.ListableWrapper {
30+
return &computeHealthCheckWrapper{
31+
client: client,
32+
ProjectBase: gcpshared.NewProjectBase(
33+
projectID,
34+
sdp.AdapterCategory_ADAPTER_CATEGORY_CONFIGURATION,
35+
ComputeHealthCheck,
36+
),
37+
}
38+
}
39+
40+
func (c computeHealthCheckWrapper) TerraformMappings() []*sdp.TerraformMapping {
41+
return []*sdp.TerraformMapping{
42+
{
43+
TerraformMethod: sdp.QueryMethod_GET,
44+
TerraformQueryMap: "google_compute_health_check.name",
45+
},
46+
}
47+
}
48+
49+
func (c computeHealthCheckWrapper) GetLookups() sources.ItemTypeLookups {
50+
return sources.ItemTypeLookups{
51+
ComputeHealthCheckLookupByName,
52+
}
53+
}
54+
55+
func (c computeHealthCheckWrapper) Get(ctx context.Context, queryParts ...string) (*sdp.Item, *sdp.QueryError) {
56+
req := &computepb.GetHealthCheckRequest{
57+
Project: c.ProjectID(),
58+
HealthCheck: queryParts[0],
59+
}
60+
61+
healthCheck, err := c.client.Get(ctx, req)
62+
if err != nil {
63+
return nil, gcpshared.QueryError(err)
64+
}
65+
66+
var sdpErr *sdp.QueryError
67+
var item *sdp.Item
68+
item, sdpErr = c.gcpComputeHealthCheckToSDPItem(healthCheck)
69+
if sdpErr != nil {
70+
return nil, sdpErr
71+
}
72+
73+
return item, nil
74+
}
75+
76+
func (c computeHealthCheckWrapper) List(ctx context.Context) ([]*sdp.Item, *sdp.QueryError) {
77+
results := c.client.List(ctx, &computepb.ListHealthChecksRequest{
78+
Project: c.ProjectID(),
79+
})
80+
81+
var items []*sdp.Item
82+
for {
83+
healthCheck, err := results.Next()
84+
if errors.Is(err, iterator.Done) {
85+
break
86+
}
87+
88+
if err != nil {
89+
return nil, gcpshared.QueryError(err)
90+
}
91+
92+
var sdpErr *sdp.QueryError
93+
var item *sdp.Item
94+
item, sdpErr = c.gcpComputeHealthCheckToSDPItem(healthCheck)
95+
if sdpErr != nil {
96+
return nil, sdpErr
97+
}
98+
99+
items = append(items, item)
100+
}
101+
102+
return items, nil
103+
}
104+
105+
// gcpComputeHealthCheckToSDPItem converts a GCP HealthCheck to an SDP Item
106+
func (c computeHealthCheckWrapper) gcpComputeHealthCheckToSDPItem(healthCheck *computepb.HealthCheck) (*sdp.Item, *sdp.QueryError) {
107+
attributes, err := shared.ToAttributesWithExclude(healthCheck)
108+
if err != nil {
109+
return nil, &sdp.QueryError{
110+
ErrorType: sdp.QueryError_OTHER,
111+
ErrorString: err.Error(),
112+
}
113+
}
114+
115+
sdpItem := &sdp.Item{
116+
Type: ComputeHealthCheck.String(),
117+
UniqueAttribute: "name",
118+
Attributes: attributes,
119+
Scope: c.DefaultScope(),
120+
}
121+
122+
//Healthcheck type has no relevant links
123+
124+
return sdpItem, nil
125+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package adapters_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"cloud.google.com/go/compute/apiv1/computepb"
8+
"go.uber.org/mock/gomock"
9+
"google.golang.org/api/iterator"
10+
"k8s.io/utils/ptr"
11+
12+
"github.com/overmindtech/cli/sources"
13+
"github.com/overmindtech/cli/sources/gcp/adapters"
14+
"github.com/overmindtech/cli/sources/gcp/shared/mocks"
15+
)
16+
17+
func TestComputeHealthCheck(t *testing.T) {
18+
ctx := context.Background()
19+
ctrl := gomock.NewController(t)
20+
defer ctrl.Finish()
21+
22+
mockClient := mocks.NewMockComputeHealthCheckClient(ctrl)
23+
projectID := "test-project-id"
24+
25+
t.Run("Get", func(t *testing.T) {
26+
wrapper := adapters.NewComputeHealthCheck(mockClient, projectID)
27+
28+
mockClient.EXPECT().Get(ctx, gomock.Any()).Return(createHealthCheck("test-healthcheck"), nil)
29+
30+
adapter := sources.WrapperToAdapter(wrapper)
31+
32+
sdpItem, qErr := adapter.Get(ctx, wrapper.Scopes()[0], "test-healthcheck", true)
33+
if qErr != nil {
34+
t.Fatalf("Expected no error, got: %v", qErr)
35+
}
36+
37+
// [SPEC] The default scope is the project ID.
38+
if sdpItem.GetScope() != "test-project-id" {
39+
t.Fatalf("Expected scope to be 'test-project-id', got: %s", sdpItem.GetScope())
40+
}
41+
42+
// [SPEC] HealthChecks have no linked items.
43+
if len(sdpItem.GetLinkedItemQueries()) != 0 {
44+
t.Fatalf("Expected 0 linked item queries, got: %d", len(sdpItem.GetLinkedItemQueries()))
45+
}
46+
47+
})
48+
49+
t.Run("List", func(t *testing.T) {
50+
wrapper := adapters.NewComputeHealthCheck(mockClient, projectID)
51+
52+
adapter := sources.WrapperToAdapter(wrapper)
53+
54+
mockComputeHealthCheckIter := mocks.NewMockComputeHealthCheckIterator(ctrl)
55+
56+
// Mock out items listed from the API.
57+
mockComputeHealthCheckIter.EXPECT().Next().Return(createHealthCheck("test-healthcheck-1"), nil)
58+
mockComputeHealthCheckIter.EXPECT().Next().Return(createHealthCheck("test-healthcheck-2"), nil)
59+
mockComputeHealthCheckIter.EXPECT().Next().Return(nil, iterator.Done)
60+
61+
// Mock the List method
62+
mockClient.EXPECT().List(ctx, gomock.Any()).Return(mockComputeHealthCheckIter)
63+
64+
sdpItems, err := adapter.List(ctx, wrapper.Scopes()[0], true)
65+
if err != nil {
66+
t.Fatalf("Expected no error, got: %v", err)
67+
}
68+
69+
if len(sdpItems) != 2 {
70+
t.Fatalf("Expected 2 items, got: %d", len(sdpItems))
71+
}
72+
73+
for _, item := range sdpItems {
74+
if item.Validate() != nil {
75+
t.Fatalf("Expected no validation error, got: %v", item.Validate())
76+
}
77+
}
78+
})
79+
}
80+
81+
func createHealthCheck(healthCheckName string) *computepb.HealthCheck {
82+
return &computepb.HealthCheck{
83+
Name: ptr.To(healthCheckName),
84+
CheckIntervalSec: ptr.To(int32(5)),
85+
TimeoutSec: ptr.To(int32(5)),
86+
Type: ptr.To("TCP"),
87+
TcpHealthCheck: &computepb.TCPHealthCheck{
88+
Port: ptr.To(int32(80)),
89+
},
90+
}
91+
}

sources/gcp/adapters/compute-node-group.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package adapters
22

33
import (
4-
"cloud.google.com/go/compute/apiv1/computepb"
54
"context"
65
"errors"
6+
7+
"cloud.google.com/go/compute/apiv1/computepb"
78
"google.golang.org/api/iterator"
89

910
"github.com/overmindtech/cli/sdp-go"

0 commit comments

Comments
 (0)