diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 472471f0..71f4d528 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -17,8 +17,7 @@ terraform { } } -provider "cdp" { -} +provider "cdp" {} resource "cdp_environments_aws_credential" "example" { name = "example-cdp-aws-credential" diff --git a/examples/resources/cdp_dw_hive/resource.tf b/examples/resources/cdp_dw_hive/resource.tf new file mode 100644 index 00000000..6a4e2595 --- /dev/null +++ b/examples/resources/cdp_dw_hive/resource.tf @@ -0,0 +1,15 @@ +## Copyright 2024 Cloudera. All Rights Reserved. +# +# This file is licensed under the Apache License Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. +# +# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +# OF ANY KIND, either express or implied. Refer to the License for the specific +# permissions and limitations governing your use of the file. + +resource "cdp_vw_hive" "example" { + cluster_id = var.cluster_id + database_catalog_id = var.database_catalog_id + name = var.name +} diff --git a/provider/provider.go b/provider/provider.go index 155f5767..a3f7f5f4 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -19,6 +19,7 @@ import ( "github.com/cloudera/terraform-provider-cdp/resources/datahub" "github.com/cloudera/terraform-provider-cdp/resources/de" + "github.com/cloudera/terraform-provider-cdp/resources/dw" "github.com/cloudera/terraform-provider-cdp/resources/iam" "github.com/cloudera/terraform-provider-cdp/resources/ml" "github.com/cloudera/terraform-provider-cdp/resources/opdb" @@ -246,6 +247,7 @@ func (p *CdpProvider) Resources(_ context.Context) []func() resource.Resource { opdb.NewDatabaseResource, ml.NewWorkspaceResource, de.NewServiceResource, + dw.NewHiveResource, } } diff --git a/provider/provider_test.go b/provider/provider_test.go index 683ecf09..b2558bdc 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -13,6 +13,7 @@ package provider import ( "context" "fmt" + "github.com/cloudera/terraform-provider-cdp/resources/dw" "os" "reflect" "regexp" @@ -632,6 +633,7 @@ func TestCdpProvider_Resources(t *testing.T) { opdb.NewDatabaseResource, ml.NewWorkspaceResource, de.NewServiceResource, + dw.NewHiveResource, } provider := CdpProvider{testVersion} diff --git a/resources/dw/model_hive_vw.go b/resources/dw/model_hive_vw.go index 41076199..b5838453 100644 --- a/resources/dw/model_hive_vw.go +++ b/resources/dw/model_hive_vw.go @@ -12,7 +12,7 @@ package dw import "github.com/hashicorp/terraform-plugin-framework/types" -type hiveVwResourceModel struct { +type hiveResourceModel struct { ID types.String `tfsdk:"id"` ClusterID types.String `tfsdk:"cluster_id"` DbCatalogID types.String `tfsdk:"database_catalog_id"` diff --git a/resources/dw/resource_hive_vw.go b/resources/dw/resource_hive_vw.go index 3b6d9cd7..fec485fb 100644 --- a/resources/dw/resource_hive_vw.go +++ b/resources/dw/resource_hive_vw.go @@ -16,51 +16,108 @@ import ( "github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/dw/client/operations" "github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/dw/models" "github.com/cloudera/terraform-provider-cdp/utils" - "github.com/cloudera/terraform-provider-cdp/utils/ptr" "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" ) -type hiveVwResource struct { +type hiveResource struct { client *cdp.Client } var ( - _ resource.Resource = (*hiveVwResource)(nil) - _ resource.ResourceWithConfigure = (*hiveVwResource)(nil) + _ resource.Resource = (*hiveResource)(nil) + _ resource.ResourceWithConfigure = (*hiveResource)(nil) ) -func (r *hiveVwResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { +func NewHiveResource() resource.Resource { + return &hiveResource{} +} + +func (r *hiveResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { r.client = utils.GetCdpClientForResource(req, resp) } -func (r *hiveVwResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_ml_workspace" +func (r *hiveResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_vw_hive" } -func (r *hiveVwResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = hiveVwSchema +func (r *hiveResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = hiveSchema } -func (r *hiveVwResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - //TODO implement me - panic("implement me") +func (r *hiveResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + // Retrieve values from plan + var plan hiveResourceModel + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + // Generate API request body from plan + vw := operations.NewCreateVwParamsWithContext(ctx). + WithInput(&models.CreateVwRequest{ + Name: plan.Name.ValueStringPointer(), + ClusterID: plan.ClusterID.ValueStringPointer(), + DbcID: plan.DbCatalogID.ValueStringPointer(), + VwType: models.VwTypeHive.Pointer(), + }) + + // Create new virtual warehouse + response, err := r.client.Dw.Operations.CreateVw(vw) + if err != nil { + resp.Diagnostics.AddError( + "Error creating hive virtual warehouse", + "Could not create hive, unexpected error: "+err.Error(), + ) + return + } + + payload := response.GetPayload() + desc := operations.NewDescribeVwParamsWithContext(ctx). + WithInput(&models.DescribeVwRequest{VwID: &payload.VwID, ClusterID: plan.ClusterID.ValueStringPointer()}) + describe, err := r.client.Dw.Operations.DescribeVw(desc) + if err != nil { + resp.Diagnostics.AddError( + "Error creating hive virtual warehouse", + "Could not describe hive, unexpected error: "+err.Error(), + ) + return + } + + hive := describe.GetPayload() + + // Map response body to schema and populate Computed attribute values + plan.ID = types.StringValue(hive.Vw.ID) + plan.DbCatalogID = types.StringValue(hive.Vw.DbcID) + plan.Name = types.StringValue(hive.Vw.Name) + // TODO why is this not accepted with error: An unexpected error was encountered trying to convert tftypes.Value into dw.hiveResourceModel. This is always an error in the provider. Please report the following to the provider developer: + //plan.LastUpdated = types.StringValue(time.Now().Format(time.RFC850)) + + // Set state to fully populated data + diags = resp.State.Set(ctx, plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } } -func (r *hiveVwResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { +func (r *hiveResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { //TODO implement me - panic("implement me") + tflog.Warn(ctx, "Read operation is not implemented yet.") } -func (r *hiveVwResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { +func (r *hiveResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { //TODO implement me - panic("implement me") + tflog.Warn(ctx, "Update operation is not implemented yet.") } -func (r *hiveVwResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - var data hiveVwResourceModel +func (r *hiveResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state hiveResourceModel - // Read Terraform prior state data into the model - resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + // Read Terraform prior state into the model + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { return @@ -68,14 +125,14 @@ func (r *hiveVwResource) Delete(ctx context.Context, req resource.DeleteRequest, op := operations.NewDeleteVwParamsWithContext(ctx). WithInput(&models.DeleteVwRequest{ - ClusterID: ptr.To(data.ClusterID.ValueString()), - VwID: ptr.To(data.ID.ValueString()), + ClusterID: state.ClusterID.ValueStringPointer(), + VwID: state.ID.ValueStringPointer(), }) if _, err := r.client.Dw.Operations.DeleteVw(op); err != nil { resp.Diagnostics.AddError( "Error deleting Hive Virtual Warehouse", - "Could not deleting Hive Virtual Warehouse, unexpected error: "+err.Error(), + "Could not delete Hive Virtual Warehouse, unexpected error: "+err.Error(), ) return } diff --git a/resources/dw/schema_hive_vw.go b/resources/dw/schema_hive_vw.go index 78fe6681..838d3b7a 100644 --- a/resources/dw/schema_hive_vw.go +++ b/resources/dw/schema_hive_vw.go @@ -16,7 +16,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" ) -var hiveVwSchema = schema.Schema{ +var hiveSchema = schema.Schema{ Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ Computed: true, diff --git a/utils/ptr/ptr.go b/utils/ptr/ptr.go deleted file mode 100644 index 33e8fca8..00000000 --- a/utils/ptr/ptr.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2024 Cloudera. All Rights Reserved. -// -// This file is licensed under the Apache License Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. -// -// This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. Refer to the License for the specific -// permissions and limitations governing your use of the file. - -package ptr - -// To creates a pointer value from `v` -func To[T any](v T) *T { - return &v -} - -// DerefDefault dereferences the `v` value if not nil otherwise it returns nil -func DerefDefault[T any](v *T, def T) T { - if v == nil { - return def - } - return *v -} - -// Copy creates a copy of the pointer which will point to the same memory address -func Copy[T any](v *T) *T { - if v == nil { - return nil - } - - cp := *v - return &cp -} diff --git a/utils/ptr/ptr_test.go b/utils/ptr/ptr_test.go deleted file mode 100644 index eb671dd2..00000000 --- a/utils/ptr/ptr_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2024 Cloudera. All Rights Reserved. -// -// This file is licensed under the Apache License Version 2.0 (the "License"). -// You may not use this file except in compliance with the License. -// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. -// -// This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. Refer to the License for the specific -// permissions and limitations governing your use of the file. - -package ptr - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestTo(t *testing.T) { - intVal := 10 - assert.Equal(t, intVal, *To(intVal)) - - stringValVal := "str" - assert.Equal(t, stringValVal, *To(stringValVal)) - - type myStruct struct { - x int - y int - } - assert.Equal(t, myStruct{1, 2}, *To(myStruct{1, 2})) -} - -func TestDerefDefault(t *testing.T) { - intVal := 10 - assert.Equal(t, 200, DerefDefault(nil, 200)) - assert.Equal(t, 10, DerefDefault(&intVal, 200)) - - stringValVal := "str" - assert.Equal(t, "default", DerefDefault(nil, "default")) - assert.Equal(t, "str", DerefDefault(&stringValVal, "default")) - - type myType struct { - x int - y int - } - - structVal := myType{1, 1} - assert.Equal(t, myType{2, 3}, DerefDefault(nil, myType{2, 3})) - assert.Equal(t, myType{1, 1}, DerefDefault(&structVal, myType{2, 3})) -} - -func TestCopy(t *testing.T) { - orig := &[]bool{true}[0] - cp := Copy(orig) - - *orig = false - assert.True(t, *cp) -} - -func TestCopyNil(t *testing.T) { - var input *bool = nil - assert.Nil(t, Copy(input)) -}