Skip to content

Commit

Permalink
CDPCP-12189 New user sync resource in environments
Browse files Browse the repository at this point in the history
  • Loading branch information
daszabo authored and gregito committed Jul 16, 2024
1 parent aafd8ed commit fad90c0
Show file tree
Hide file tree
Showing 6 changed files with 246 additions and 0 deletions.
39 changes: 39 additions & 0 deletions docs/resources/environments_user_sync.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
page_title: "cdp_environments_user_sync Resource - terraform-provider-cdp"
subcategory: "environments"
description: |-
Synchronizes environments with all users and groups state with CDP.
---

# cdp_environments_user_sync (Resource)

Synchronizes environments with all users and groups state with CDP.

## Example Usage

```terraform
## 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_environments_user_sync" "example-user_sync" {
environment_names = ["example-cdp-environment-1", "example-cdp-environment-2"]
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `environment_names` (Set of String) List of environments to be synced. If not present, all environments will be synced.

### Read-Only

- `id` (String) The ID of this resource.
13 changes: 13 additions & 0 deletions examples/resources/cdp_environments_user_sync/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## 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_environments_user_sync" "example-user_sync" {
environment_names = ["example-cdp-environment-1", "example-cdp-environment-2"]
}
1 change: 1 addition & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ func (p *CdpProvider) Resources(_ context.Context) []func() resource.Resource {
environments.NewAwsCredentialResource,
environments.NewAwsEnvironmentResource,
environments.NewIDBrokerMappingsResource,
environments.NewUserSyncResource,
environments.NewAzureCredentialResource,
environments.NewAzureEnvironmentResource,
environments.NewAzureImageTermsResource,
Expand Down
1 change: 1 addition & 0 deletions provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ func TestCdpProvider_Resources(t *testing.T) {
environments.NewAwsCredentialResource,
environments.NewAwsEnvironmentResource,
environments.NewIDBrokerMappingsResource,
environments.NewUserSyncResource,
environments.NewAzureCredentialResource,
environments.NewAzureEnvironmentResource,
environments.NewGcpEnvironmentResource,
Expand Down
166 changes: 166 additions & 0 deletions resources/environments/resource_user_sync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// 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 environments

import (
"context"

"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/cdp"
"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/environments/client/operations"
environmentsmodels "github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/environments/models"
"github.com/cloudera/terraform-provider-cdp/utils"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
)

var (
_ resource.Resource = &userSyncResource{}
)

var userSyncSchema = schema.Schema{
MarkdownDescription: "Synchronizes environments with all users and groups state with CDP.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"environment_names": schema.SetAttribute{
MarkdownDescription: "List of environments to be synced. If not present, all environments will be synced.",
ElementType: types.StringType,
Optional: true,
},
},
}

type userSyncResource struct {
client *cdp.Client
}

func NewUserSyncResource() resource.Resource {
return &userSyncResource{}
}

func (r *userSyncResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_environments_user_sync"
}

type userSyncResourceModel struct {
ID types.String `tfsdk:"id"`

EnvironmentNames types.Set `tfsdk:"environment_names"`
}

func toSyncAllUsersRequest(ctx context.Context, model *userSyncResourceModel, diag *diag.Diagnostics) *environmentsmodels.SyncAllUsersRequest {
req := &environmentsmodels.SyncAllUsersRequest{}
req.EnvironmentNames = utils.FromSetValueToStringList(model.EnvironmentNames)
return req
}

func (r *userSyncResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = userSyncSchema
}

func (r *userSyncResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
r.client = utils.GetCdpClientForResource(req, resp)
}

func (r *userSyncResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var state userSyncResourceModel
diags := req.Plan.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Got Error while trying to set plan")
return
}

client := r.client.Environments

params := operations.NewSyncAllUsersParamsWithContext(ctx)
params.WithInput(toSyncAllUsersRequest(ctx, &state, &resp.Diagnostics))
_, err := client.Operations.SyncAllUsers(params)
if err != nil {
if isSyncAllUsersNotFoundError(err) {
resp.Diagnostics.AddError(
"Error in sync all users",
"An environment not found: "+state.EnvironmentNames.String(),
)
return
}
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "sync all users")
return
}

state.ID = types.StringValue(uuid.New().String())

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

func isSyncAllUsersNotFoundError(err error) bool {
if envErr, ok := err.(*operations.SyncAllUsersDefault); ok {
if cdp.IsEnvironmentsError(envErr.GetPayload(), "NOT_FOUND", "") {
return true
}
}
return false
}

func (r *userSyncResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
tflog.Info(ctx, "Nothing to do in read phase")
}

func (r *userSyncResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var state userSyncResourceModel
diags := req.Plan.Get(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Got Error while trying to set plan")
return
}

client := r.client.Environments

params := operations.NewSyncAllUsersParamsWithContext(ctx)
params.WithInput(toSyncAllUsersRequest(ctx, &state, &resp.Diagnostics))
_, err := client.Operations.SyncAllUsers(params)
if err != nil {
if isSyncAllUsersNotFoundError(err) {
resp.Diagnostics.AddError(
"Error in sync all users",
"An environment not found: "+state.EnvironmentNames.String(),
)
return
}
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "sync all users")
return
}

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

func (r *userSyncResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
tflog.Info(ctx, "Nothing to do in delete phase")
}
26 changes: 26 additions & 0 deletions templates/resources/environments_user_sync.md.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
subcategory: "{{ index (split .Name "_") 1}}"
description: |-
{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
---

# {{.Name}} ({{.Type}})

{{ .Description | trimspace }}

{{ if .HasExample -}}
## Example Usage

{{ tffile .ExampleFile }}
{{- end }}

{{ .SchemaMarkdown | trimspace }}

{{- if .HasImport }}
## Import

Import is supported using the following syntax:

{{codefile "shell" .ImportFile }}
{{- end }}

0 comments on commit fad90c0

Please sign in to comment.