Skip to content

Commit

Permalink
Refactor custom request handling to introduce graphcustom package; im…
Browse files Browse the repository at this point in the history
…plement ByIDRequestUrlTemplate and PutRequestByResourceId functions for improved URL construction and PUT request management. Update existing CRUD operations to utilize new configurations, enhancing code organization and maintainability.
ShocOne committed Dec 1, 2024
1 parent 04140fd commit 99a8669
Showing 6 changed files with 65 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package client
package graphcustom

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"

"github.com/hashicorp/terraform-plugin-log/tflog"
abstractions "github.com/microsoft/kiota-abstractions-go"
)

// CustomGetRequestConfig contains the configuration for a custom GET request
type CustomGetRequestConfig struct {
// GetRequestConfig contains the configuration for a custom GET request
type GetRequestConfig struct {
// The API version to use (beta or v1.0)
APIVersion GraphAPIVersion
// The base endpoint (e.g., "deviceManagement/configurationPolicies")
@@ -36,7 +35,7 @@ type ODataResponse struct {
NextLink string `json:"@odata.nextLink,omitempty"`
}

// SendCustomGetRequestByResourceId performs a custom GET request using the Microsoft Graph SDK when the operation
// GetRequestByResourceId performs a custom GET request using the Microsoft Graph SDK when the operation
// is not available in the generated SDK methods or when using raw json is easier to handle for response handling.
// This function supports both Beta and V1.0 Graph API versions and automatically handles OData pagination if present.
//
@@ -53,7 +52,7 @@ type ODataResponse struct {
// Parameters:
// - ctx: The context for the request, which can be used for cancellation and timeout
// - adapter: The request adapter for sending the request
// - config: CustomGetRequestConfig containing:
// - config: GetRequestConfig containing:
// - APIVersion: The Graph API version to use (Beta or V1.0)
// - Endpoint: The resource endpoint path (e.g., "/deviceManagement/configurationPolicies")
// - ResourceID: The ID of the resource to retrieve
@@ -68,7 +67,7 @@ type ODataResponse struct {
//
// Example Usage:
//
// config := CustomGetRequestConfig{
// config := GetRequestConfig{
// APIVersion: GraphAPIBeta,
// Endpoint: "/deviceManagement/configurationPolicies",
// ResourceID: "d557c813-b8e5-4efc-b00e-9c0bd5fd10df",
@@ -79,13 +78,13 @@ type ODataResponse struct {
// },
// }
//
// response, err := SendCustomGetRequestByResourceId(ctx, adapter, config)
// response, err := GetRequestByResourceId(ctx, adapter, config)
// if err != nil {
// log.Fatalf("Error: %v", err)
// }
//
// fmt.Printf("Response: %+v\n", response)
func SendCustomGetRequestByResourceId(ctx context.Context, adapter abstractions.RequestAdapter, reqConfig CustomGetRequestConfig) (json.RawMessage, error) {
func GetRequestByResourceId(ctx context.Context, adapter abstractions.RequestAdapter, reqConfig GetRequestConfig) (json.RawMessage, error) {

requestInfo := abstractions.NewRequestInformation()
requestInfo.Method = abstractions.GET
@@ -160,30 +159,6 @@ func SendCustomGetRequestByResourceId(ctx context.Context, adapter abstractions.
return json.Marshal(combinedResponse)
}

// ByIDRequestUrlTemplate constructs a URL template for a single resource request using the provided configuration.
// The function combines the endpoint path with a resource ID and optional suffix to create a complete URL template.
// For example, if the config contains:
// - Endpoint: "/deviceManagement/configurationPolicies"
// - ResourceIDPattern: "('id')"
// - ResourceID: "12345"
// - EndpointSuffix: "/settings"
//
// The resulting template would be: "{+baseurl}/deviceManagement/configurationPolicies('12345')/settings"
//
// Parameters:
// - reqConfig: CustomGetRequestConfig containing the endpoint path, resource ID pattern, actual ID, and optional suffix
//
// Returns:
// - string: The constructed URL template ready for use with the Kiota request adapter
func ByIDRequestUrlTemplate(reqConfig CustomGetRequestConfig) string {
idFormat := strings.ReplaceAll(reqConfig.ResourceIDPattern, "id", reqConfig.ResourceID)
endpoint := reqConfig.Endpoint + idFormat
if reqConfig.EndpointSuffix != "" {
endpoint += reqConfig.EndpointSuffix
}
return "{+baseurl}" + endpoint
}

// makeRequest executes an HTTP request using the provided Kiota request adapter and request information.
// This helper function handles the conversion of Kiota's RequestInformation into a native HTTP request,
// executes the request, and returns the raw response body.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package client
package graphcustom

import (
"context"
@@ -8,8 +8,8 @@ import (
s "github.com/microsoft/kiota-abstractions-go/serialization"
)

// CustomPostRequestConfig contains the configuration for a custom POST request
type CustomPostRequestConfig struct {
// PostRequestConfig contains the configuration for a custom POST request
type PostRequestConfig struct {
// The API version to use (beta or v1.0)
APIVersion GraphAPIVersion
// The base endpoint (e.g., "/deviceManagement/configurationPolicies")
@@ -20,14 +20,14 @@ type CustomPostRequestConfig struct {
QueryParameters map[string]string
}

// SendCustomPostRequest performs a custom POST request using the Microsoft Graph SDK when the operation
// PostRequest performs a custom POST request using the Microsoft Graph SDK when the operation
// is not available in the generated SDK methods. This function supports both Beta and V1.0 Graph API versions
// and returns the parsed response model.
//
// Parameters:
// - ctx: The context for the request, which can be used for cancellation and timeout
// - adapter: The RequestAdapter interface for making HTTP requests
// - config: CustomPostRequestConfig containing:
// - config: PostRequestConfig containing:
// - APIVersion: The Graph API version to use (Beta or V1.0)
// - Endpoint: The resource endpoint path
// - RequestBody: The body of the POST request implementing serialization.Parsable
@@ -38,10 +38,10 @@ type CustomPostRequestConfig struct {
// Returns:
// - s.Parsable: The parsed response model
// - error: Any error that occurred during the request
func SendCustomPostRequest(
func PostRequest(
ctx context.Context,
adapter abstractions.RequestAdapter,
config CustomPostRequestConfig,
config PostRequestConfig,
factory s.ParsableFactory,
errorMappings abstractions.ErrorMappings,
) (s.Parsable, error) {
@@ -74,16 +74,16 @@ func SendCustomPostRequest(
return result, nil
}

// SendCustomPostRequestNoContent performs a custom POST request that doesn't expect a response body.
// PostRequestNoContent performs a custom POST request that doesn't expect a response body.
// This is useful for operations that return 204 No Content.
//
// Parameters are the same as SendCustomPostRequest except it doesn't take a responseModel parameter
// Parameters are the same as PostRequest except it doesn't take a responseModel parameter
// and uses the SendNoContent method of the adapter.
//
// Returns:
// - error: Returns nil if the request was successful (204 No Content received),
// otherwise returns an error describing what went wrong
func SendCustomPostRequestNoContent(ctx context.Context, adapter abstractions.RequestAdapter, config CustomPostRequestConfig) error {
func PostRequestNoContent(ctx context.Context, adapter abstractions.RequestAdapter, config PostRequestConfig) error {
requestInfo := abstractions.NewRequestInformation()
requestInfo.Method = abstractions.POST
requestInfo.UrlTemplate = "{+baseurl}/" + config.Endpoint
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package client
package graphcustom

import (
"context"
@@ -16,8 +16,8 @@ const (
GraphAPIV1 GraphAPIVersion = "v1.0"
)

// CustomPutRequestConfig contains the configuration for a custom PUT request
type CustomPutRequestConfig struct {
// PutRequestConfig contains the configuration for a custom PUT request
type PutRequestConfig struct {
// The API version to use (beta or v1.0)
APIVersion GraphAPIVersion
// The base endpoint (e.g., "/deviceManagement/configurationPolicies")
@@ -28,7 +28,7 @@ type CustomPutRequestConfig struct {
RequestBody s.Parsable
}

// SendCustomPutRequestByResourceId performs a custom PUT request using the Microsoft Graph SDK when the operation
// PutRequestByResourceId performs a custom PUT request using the Microsoft Graph SDK when the operation
// is not available in the generated SDK methods. This function supports both Beta and V1.0 Graph API versions
// and expects a 204 No Content response from the server on success.
//
@@ -61,8 +61,8 @@ type CustomPutRequestConfig struct {
// ResourceID: "d557c813-b8e5-4efc-b00e-9c0bd5fd10df",
// RequestBody: myRequestBody,
// }
// err := SendCustomPutRequestByResourceId(ctx, clients, config)
func SendCustomPutRequestByResourceId(ctx context.Context, adapter abstractions.RequestAdapter, config CustomPutRequestConfig) error {
// err := PutRequestByResourceId(ctx, clients, config)
func PutRequestByResourceId(ctx context.Context, adapter abstractions.RequestAdapter, config PutRequestConfig) error {
requestInfo := abstractions.NewRequestInformation()
requestInfo.Method = abstractions.PUT
requestInfo.UrlTemplate = "{+baseurl}" + config.Endpoint + "('{id}')"
27 changes: 27 additions & 0 deletions internal/client/graphcustom/url_templates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package graphcustom

import "strings"

// ByIDRequestUrlTemplate constructs a URL template for a single resource request using the provided configuration.
// The function combines the endpoint path with a resource ID and optional suffix to create a complete URL template.
// For example, if the config contains:
// - Endpoint: "/deviceManagement/configurationPolicies"
// - ResourceIDPattern: "('id')"
// - ResourceID: "12345"
// - EndpointSuffix: "/settings"
//
// The resulting template would be: "{+baseurl}/deviceManagement/configurationPolicies('12345')/settings"
//
// Parameters:
// - reqConfig: GetRequestConfig containing the endpoint path, resource ID pattern, actual ID, and optional suffix
//
// Returns:
// - string: The constructed URL template ready for use with the Kiota request adapter
func ByIDRequestUrlTemplate(reqConfig GetRequestConfig) string {
idFormat := strings.ReplaceAll(reqConfig.ResourceIDPattern, "id", reqConfig.ResourceID)
endpoint := reqConfig.Endpoint + idFormat
if reqConfig.EndpointSuffix != "" {
endpoint += reqConfig.EndpointSuffix
}
return "{+baseurl}" + endpoint
}
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import (
"sync"
"time"

"github.com/deploymenttheory/terraform-provider-microsoft365/internal/client"
"github.com/deploymenttheory/terraform-provider-microsoft365/internal/client/graphcustom"
"github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/crud"
"github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/errors"
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -276,14 +276,14 @@ func (r *EndpointPrivilegeManagementResource) Update(ctx context.Context, req re
return
}

putRequest := client.CustomPutRequestConfig{
APIVersion: client.GraphAPIBeta,
putRequest := graphcustom.PutRequestConfig{
APIVersion: graphcustom.GraphAPIBeta,
Endpoint: "deviceManagement/configurationPolicies",
ResourceID: object.ID.ValueString(),
RequestBody: requestBody,
}

err = client.SendCustomPutRequestByResourceId(ctx, r.client.GetAdapter(), putRequest)
err = graphcustom.PutRequestByResourceId(ctx, r.client.GetAdapter(), putRequest)
if err != nil {
errors.HandleGraphError(ctx, err, resp, "Update", r.ReadPermissions)
return
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import (
"sync"
"time"

"github.com/deploymenttheory/terraform-provider-microsoft365/internal/client"
"github.com/deploymenttheory/terraform-provider-microsoft365/internal/client/graphcustom"
"github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/crud"
"github.com/deploymenttheory/terraform-provider-microsoft365/internal/resources/common/errors"
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -109,8 +109,8 @@ func (r *SettingsCatalogResource) Create(ctx context.Context, req resource.Creat
}
MapRemoteResourceStateToTerraform(ctx, &object, respResource)

settingsConfig := client.CustomGetRequestConfig{
APIVersion: client.GraphAPIBeta,
settingsConfig := graphcustom.GetRequestConfig{
APIVersion: graphcustom.GraphAPIBeta,
Endpoint: r.ResourcePath,
EndpointSuffix: "/settings",
ResourceIDPattern: "('id')",
@@ -120,7 +120,7 @@ func (r *SettingsCatalogResource) Create(ctx context.Context, req resource.Creat
},
}

respSettings, err := client.SendCustomGetRequestByResourceId(
respSettings, err := graphcustom.GetRequestByResourceId(
ctx,
r.client.GetAdapter(),
settingsConfig,
@@ -198,8 +198,8 @@ func (r *SettingsCatalogResource) Read(ctx context.Context, req resource.ReadReq

MapRemoteResourceStateToTerraform(ctx, &object, respResource)

settingsConfig := client.CustomGetRequestConfig{
APIVersion: client.GraphAPIBeta,
settingsConfig := graphcustom.GetRequestConfig{
APIVersion: graphcustom.GraphAPIBeta,
Endpoint: r.ResourcePath,
EndpointSuffix: "/settings",
ResourceIDPattern: "('id')",
@@ -209,7 +209,7 @@ func (r *SettingsCatalogResource) Read(ctx context.Context, req resource.ReadReq
},
}

respSettings, err := client.SendCustomGetRequestByResourceId(
respSettings, err := graphcustom.GetRequestByResourceId(
ctx,
r.client.GetAdapter(),
settingsConfig,
@@ -281,14 +281,14 @@ func (r *SettingsCatalogResource) Update(ctx context.Context, req resource.Updat
return
}

putRequest := client.CustomPutRequestConfig{
APIVersion: client.GraphAPIBeta,
putRequest := graphcustom.PutRequestConfig{
APIVersion: graphcustom.GraphAPIBeta,
Endpoint: r.ResourcePath,
ResourceID: object.ID.ValueString(),
RequestBody: requestBody,
}

err = client.SendCustomPutRequestByResourceId(ctx, r.client.GetAdapter(), putRequest)
err = graphcustom.PutRequestByResourceId(ctx, r.client.GetAdapter(), putRequest)
if err != nil {
errors.HandleGraphError(ctx, err, resp, "Update", r.ReadPermissions)
return

0 comments on commit 99a8669

Please sign in to comment.