Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Migrate license map resource from SDKv2 to plugin framework #325

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/resources/license_map.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
page_title: "dbtcloud_license_map Resource - dbtcloud"
subcategory: ""
description: |-

Maps SSO groups to a given license type
---

# dbtcloud_license_map (Resource)



Maps SSO groups to a given license type

## Example Usage

Expand Down Expand Up @@ -45,7 +45,7 @@ resource "dbtcloud_license_map" "it_license_map" {

### Read-Only

- `id` (String) The ID of this resource.
chasewalden marked this conversation as resolved.
Show resolved Hide resolved
- `id` (Number) The ID of the license map

## Import

Expand Down
3 changes: 1 addition & 2 deletions pkg/framework/objects/group/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package group

import (
"context"
"fmt"
"strconv"
"strings"

Expand Down Expand Up @@ -263,7 +262,7 @@ func (r *groupResource) ImportState(
groupIDStr := req.ID
groupID, err := strconv.Atoi(groupIDStr)
if err != nil {
fmt.Println(err)
resp.Diagnostics.AddError("Error parsing group ID for import", err.Error())
return
}

Expand Down
11 changes: 11 additions & 0 deletions pkg/framework/objects/license_map/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package license_map

import (
"github.com/hashicorp/terraform-plugin-framework/types"
)

type LicenseMapResourceModel struct {
ID types.Int64 `tfsdk:"id"`
LicenseType types.String `tfsdk:"license_type"`
SSOLicenseMappingGroups types.Set `tfsdk:"sso_license_mapping_groups"`
}
240 changes: 240 additions & 0 deletions pkg/framework/objects/license_map/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package license_map

import (
"context"
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/dbt_cloud"
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/helper"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/samber/lo"
"strconv"
"strings"
)

var (
_ resource.Resource = &licenseMapResource{}
_ resource.ResourceWithConfigure = &licenseMapResource{}

licenseTypes = []string{
"developer",
"read_only",
"it",
}
)

func LicenseMapResource() resource.Resource {
return &licenseMapResource{}
}

type licenseMapResource struct {
client *dbt_cloud.Client
}

func (r *licenseMapResource) Metadata(
_ context.Context,
req resource.MetadataRequest,
resp *resource.MetadataResponse,
) {
resp.TypeName = req.ProviderTypeName + "_license_map"
}

func (r *licenseMapResource) Read(
ctx context.Context,
req resource.ReadRequest,
resp *resource.ReadResponse,
) {
var state LicenseMapResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &state)...)

licenseMapID := state.ID.ValueInt64()
licenseMap, err := r.client.GetLicenseMap(int(licenseMapID))
if err != nil {
if strings.HasPrefix(err.Error(), "resource-not-found") {
resp.Diagnostics.AddWarning(
"Resource not found",
"The license map resource was not found and has been removed from the state.",
)
resp.State.RemoveResource(ctx)
return
}
resp.Diagnostics.AddError("Error getting the license map", err.Error())
return
}

state.ID = types.Int64Value(int64(*licenseMap.ID))
state.LicenseType = types.StringValue(licenseMap.LicenseType)
state.SSOLicenseMappingGroups, _ = types.SetValueFrom(
context.Background(),
types.StringType,
licenseMap.SSOLicenseMappingGroups,
)

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (r *licenseMapResource) Create(
ctx context.Context,
req resource.CreateRequest,
resp *resource.CreateResponse,
) {
var plan LicenseMapResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
if resp.Diagnostics.HasError() {
return
}

var configSsoMapping []string
diags := plan.SSOLicenseMappingGroups.ElementsAs(
context.Background(),
&configSsoMapping,
false,
)
if diags.HasError() {
resp.Diagnostics.AddError("Error extracting the list of SSO groups", "")
return
}

licenseMap, err := r.client.CreateLicenseMap(
plan.LicenseType.ValueString(),
configSsoMapping,
)

if err != nil {
resp.Diagnostics.AddError(
"Unable to create license map",
"Error: "+err.Error(),
)
return
}

plan.ID = types.Int64PointerValue(helper.IntPointerToInt64Pointer(licenseMap.ID))
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
}

func (r *licenseMapResource) Delete(
ctx context.Context,
req resource.DeleteRequest,
resp *resource.DeleteResponse,
) {
var state LicenseMapResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

licenseMapID := int(state.ID.ValueInt64())

err := r.client.DestroyLicenseMap(licenseMapID)
if err != nil {
resp.Diagnostics.AddError("Error deleting the license map", err.Error())
return
}
}

func (r *licenseMapResource) Update(
ctx context.Context,
req resource.UpdateRequest,
resp *resource.UpdateResponse,
) {
var plan, state LicenseMapResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
if resp.Diagnostics.HasError() {
return
}

licenseMapID := int(state.ID.ValueInt64())
licenseMap, err := r.client.GetLicenseMap(licenseMapID)
if err != nil {
resp.Diagnostics.AddError(
"Error getting the license map",
"Error: "+err.Error(),
)
return
}

var planSsoMapping []string
diags := plan.SSOLicenseMappingGroups.ElementsAs(
context.Background(),
&planSsoMapping,
false,
)
if diags.HasError() {
resp.Diagnostics.AddError("Error extracting the list of SSO groups from the plan", "")
return
}

var stateSsoMapping []string
diags = state.SSOLicenseMappingGroups.ElementsAs(
context.Background(),
&stateSsoMapping,
false,
)
if diags.HasError() {
resp.Diagnostics.AddError("Error extracting the list of SSO groups from the state", "")
return
}

deletedSsoMapping, newSsoMapping := lo.Difference(stateSsoMapping, planSsoMapping)
hasMappingChanges := len(deletedSsoMapping) > 0 || len(newSsoMapping) > 0

if state.LicenseType != plan.LicenseType || hasMappingChanges {
if state.LicenseType != plan.LicenseType {
licenseMap.LicenseType = plan.LicenseType.ValueString()
}

if hasMappingChanges {
licenseMap.SSOLicenseMappingGroups = planSsoMapping
}

_, err = r.client.UpdateLicenseMap(licenseMapID, *licenseMap)
if err != nil {
resp.Diagnostics.AddError(
"Unable to update the existing license map",
"Error: "+err.Error(),
)
return
}
}

resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
}

func (r *licenseMapResource) ImportState(
ctx context.Context,
req resource.ImportStateRequest,
resp *resource.ImportStateResponse,
) {
licenseMapID, err := strconv.Atoi(req.ID)
if err != nil {
resp.Diagnostics.AddError("Error parsing license map ID for import", err.Error())
return
}
ssoLicenseMappingGroups, _ := types.SetValue(types.StringType, nil)
state := LicenseMapResourceModel{
ID: types.Int64Value(int64(licenseMapID)),
SSOLicenseMappingGroups: ssoLicenseMappingGroups,
}

diags := resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

func (r *licenseMapResource) Configure(
_ context.Context,
req resource.ConfigureRequest,
_ *resource.ConfigureResponse,
) {
if req.ProviderData == nil {
return
}

r.client = req.ProviderData.(*dbt_cloud.Client)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package resources_test
package license_map_test

import (
"fmt"
Expand All @@ -18,7 +18,7 @@ func TestAccDbtCloudLicenseMapResource(t *testing.T) {
groupName2 := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
PreCheck: func() { acctest_helper.TestAccPreCheck(t) },
ProtoV6ProviderFactories: acctest_helper.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckDbtCloudLicenseMapDestroy,
Steps: []resource.TestStep{
Expand Down
46 changes: 46 additions & 0 deletions pkg/framework/objects/license_map/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package license_map

import (
"context"
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/helper"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)

func (r *licenseMapResource) Schema(
_ context.Context,
_ resource.SchemaRequest,
resp *resource.SchemaResponse,
) {
resp.Schema = schema.Schema{
Description: helper.DocString(
`Maps SSO groups to a given license type`,
),
Attributes: map[string]schema.Attribute{
"id": schema.Int64Attribute{
Computed: true,
Description: "The ID of the license map",
PlanModifiers: []planmodifier.Int64{
int64planmodifier.UseStateForUnknown(),
},
},
"license_type": schema.StringAttribute{
Required: true,
Description: "License type",
Validators: []validator.String{
stringvalidator.OneOf(licenseTypes...),
},
},
"sso_license_mapping_groups": schema.SetAttribute{
Optional: true,
Description: "SSO license mapping group names for this group",
ElementType: types.StringType,
},
},
}
}
3 changes: 1 addition & 2 deletions pkg/framework/objects/oauth_configuration/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package oauth_configuration

import (
"context"
"fmt"
"strconv"
"strings"

Expand Down Expand Up @@ -267,7 +266,7 @@ func (r *oAuthConfigurationResource) ImportState(
oAuthConfigurationIDStr := req.ID
oAuthConfigurationID, err := strconv.Atoi(oAuthConfigurationIDStr)
if err != nil {
fmt.Println(err)
resp.Diagnostics.AddError("Error parsing OAuth configuration ID for import", err.Error())
return
}

Expand Down
10 changes: 2 additions & 8 deletions pkg/framework/objects/partial_license_map/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@ package partial_license_map

import (
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/dbt_cloud"
"github.com/dbt-labs/terraform-provider-dbtcloud/pkg/framework/objects/license_map"
"github.com/hashicorp/terraform-plugin-framework/types"
)

// TODO: Move the model to the non partial when moved to the Framework
type LicenseMapResourceModel struct {
ID types.Int64 `tfsdk:"id"`
LicenseType types.String `tfsdk:"license_type"`
SSOLicenseMappingGroups types.Set `tfsdk:"sso_license_mapping_groups"`
}

func matchPartial(
licenseMapModel LicenseMapResourceModel,
licenseMapModel license_map.LicenseMapResourceModel,
licenseTypeResponse dbt_cloud.LicenseMap,
) bool {
return licenseMapModel.LicenseType == types.StringValue(licenseTypeResponse.LicenseType)
Expand Down
Loading
Loading