From b1f5760259241508981355453880e43330297d16 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 6 Feb 2024 07:06:28 +0100 Subject: [PATCH] `tools/data-api-sdk`: scaffolding out the Data API SDK This commit introduces the new Data API SDK such that it can be used elsewhere. At this point in time this only supports the Health endpoint - but threads through the `Available Source Data Type` concept too - which enables other tools to be updated. --- tools/data-api-sdk/.gitignore | 1 + tools/data-api-sdk/README.md | 27 ++++++++++++++ tools/data-api-sdk/go.mod | 7 ++++ tools/data-api-sdk/go.sum | 9 +++++ .../v1/available_source_data_types.go | 13 +++++++ tools/data-api-sdk/v1/client.go | 30 ++++++++++++++++ tools/data-api-sdk/v1/health.go | 35 +++++++++++++++++++ .../v1/models/source_data_types.go | 12 +++++++ 8 files changed, 134 insertions(+) create mode 100644 tools/data-api-sdk/.gitignore create mode 100644 tools/data-api-sdk/README.md create mode 100644 tools/data-api-sdk/go.mod create mode 100644 tools/data-api-sdk/go.sum create mode 100644 tools/data-api-sdk/v1/available_source_data_types.go create mode 100644 tools/data-api-sdk/v1/client.go create mode 100644 tools/data-api-sdk/v1/health.go create mode 100644 tools/data-api-sdk/v1/models/source_data_types.go diff --git a/tools/data-api-sdk/.gitignore b/tools/data-api-sdk/.gitignore new file mode 100644 index 00000000000..a725465aee2 --- /dev/null +++ b/tools/data-api-sdk/.gitignore @@ -0,0 +1 @@ +vendor/ \ No newline at end of file diff --git a/tools/data-api-sdk/README.md b/tools/data-api-sdk/README.md new file mode 100644 index 00000000000..9f5916bb5bd --- /dev/null +++ b/tools/data-api-sdk/README.md @@ -0,0 +1,27 @@ +## `./tools/data-api-sdk` + +This package provides a Go SDK (and thus common models) which allows querying the Data API. + +### Example Usage + +```go +package main + +import ( + "context" + "log" + + "github.com/hashicorp/pandora/tools/data-api-sdk/v1" + "github.com/hashicorp/pandora/tools/data-api-sdk/v1/models" +) + +func main() { + ctx := context.TODO() + client := v1.NewClient("http://localhost:8888", models.ResourceManagerSourceDataType) + resp, err := client.Health(ctx) + if err != nil { + log.Fatalf("%+v", err) + } + log.Printf("Data API is available: %t", resp.Available) +} +``` \ No newline at end of file diff --git a/tools/data-api-sdk/go.mod b/tools/data-api-sdk/go.mod new file mode 100644 index 00000000000..a46bc40f097 --- /dev/null +++ b/tools/data-api-sdk/go.mod @@ -0,0 +1,7 @@ +module github.com/hashicorp/pandora/tools/data-api-sdk + +go 1.21 + +require github.com/hashicorp/go-retryablehttp v0.7.5 + +require github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/tools/data-api-sdk/go.sum b/tools/data-api-sdk/go.sum new file mode 100644 index 00000000000..16f60f4e73d --- /dev/null +++ b/tools/data-api-sdk/go.sum @@ -0,0 +1,9 @@ +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/tools/data-api-sdk/v1/available_source_data_types.go b/tools/data-api-sdk/v1/available_source_data_types.go new file mode 100644 index 00000000000..e72cf2a4151 --- /dev/null +++ b/tools/data-api-sdk/v1/available_source_data_types.go @@ -0,0 +1,13 @@ +package v1 + +import "github.com/hashicorp/pandora/tools/data-api-sdk/v1/models" + +// AvailableSourceDataTypes returns a list of the supported Source Data Types. +// This can be used to allow tooling to automatically support new Source Data +// Types as these are defined here, for example by using this information in CLIs. +func AvailableSourceDataTypes() []models.SourceDataType { + return []models.SourceDataType{ + models.MicrosoftGraphSourceDataType, + models.ResourceManagerSourceDataType, + } +} diff --git a/tools/data-api-sdk/v1/client.go b/tools/data-api-sdk/v1/client.go new file mode 100644 index 00000000000..8c934cbe88c --- /dev/null +++ b/tools/data-api-sdk/v1/client.go @@ -0,0 +1,30 @@ +package v1 + +import ( + "net/http" + + "github.com/hashicorp/pandora/tools/data-api-sdk/v1/models" +) + +type Client struct { + // client is the HTTP Client used for HTTP requests + client *http.Client + + // endpoint specifies the base endpoint for the Data API. + // Typically this will be `http://localhost:8080` but can vary. + endpoint string + + // sourceDataType specifies the Data Source Type being queried. + sourceDataType models.SourceDataType +} + +// NewClient returns an instance of Client configured for the current endpoint +// and sourceDataType combination - used to retrieve information from the Data API. +func NewClient(endpoint string, sourceDataType models.SourceDataType) *Client { + return &Client{ + // NOTE: this is retryable to account for tooling interfering with connections + client: retryablehttp.NewClient().StandardClient(), + endpoint: endpoint, + sourceDataType: sourceDataType, + } +} diff --git a/tools/data-api-sdk/v1/health.go b/tools/data-api-sdk/v1/health.go new file mode 100644 index 00000000000..d6e439bd333 --- /dev/null +++ b/tools/data-api-sdk/v1/health.go @@ -0,0 +1,35 @@ +package v1 + +import ( + "context" + "fmt" + "net/http" +) + +type HealthResponse struct { + // Available specifies whether the Data API is available or not. + Available bool + + // HttpResponse is the raw HTTP Response + HttpResponse *http.Response +} + +// Health checks the current status of the Data API, returning whether it's ready +// to accept requests or not. +func (c *Client) Health(ctx context.Context) (*HealthResponse, error) { + uri := fmt.Sprintf("%s/v1/health", c.endpoint) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) + if err != nil { + return nil, fmt.Errorf("checking the health endpoint: %+v", err) + } + + resp, err := c.client.Do(req) + if err != nil { + return nil, fmt.Errorf("performing request: %+v", err) + } + + return &HealthResponse{ + Available: resp.StatusCode == http.StatusOK, + HttpResponse: resp, + }, nil +} diff --git a/tools/data-api-sdk/v1/models/source_data_types.go b/tools/data-api-sdk/v1/models/source_data_types.go new file mode 100644 index 00000000000..d11ed399ba2 --- /dev/null +++ b/tools/data-api-sdk/v1/models/source_data_types.go @@ -0,0 +1,12 @@ +package models + +// SourceDataType defines a type of Source Data. +type SourceDataType string + +const ( + // MicrosoftGraphSourceDataType defines that this Data is related to Microsoft Graph. + MicrosoftGraphSourceDataType SourceDataType = "microsoft-graph" + + // ResourceManagerSourceDataType defines that this Data is related to Azure Resource Manager. + ResourceManagerSourceDataType SourceDataType = "resource-manager" +)