-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CDPCP-9883 - GCP credential create/delete/read (#25)
- Loading branch information
Showing
9 changed files
with
384 additions
and
0 deletions.
There are no files selected for viewing
32 changes: 32 additions & 0 deletions
32
examples/resources/cdp_environments_gcp_credential/resource.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
## Copyright 2023 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. | ||
|
||
terraform { | ||
required_providers { | ||
cdp = { | ||
source = "registry.terraform.io/cloudera/cdp" | ||
} | ||
} | ||
} | ||
|
||
resource "cdp_environments_gcp_credential" "example" { | ||
credential_name = "cdp-gcp-credential" | ||
credential_key = "<BASE64 content>" | ||
description = "Example GCP Credentials" | ||
} | ||
|
||
output "credential_name" { | ||
value = cdp_environments_gcp_credential.example.credential_name | ||
} | ||
|
||
output "credential_key" { | ||
value = cdp_environments_gcp_credential.example.credential_key | ||
sensitive = true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright 2023 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 "github.com/hashicorp/terraform-plugin-framework/types" | ||
|
||
type gcpCredentialResourceModel struct { | ||
ID types.String `tfsdk:"id"` | ||
CredentialName types.String `tfsdk:"credential_name"` | ||
CredentialKey types.String `tfsdk:"credential_key"` | ||
Crn types.String `tfsdk:"crn"` | ||
Description types.String `tfsdk:"description"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
// Copyright 2023 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" | ||
"encoding/base64" | ||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
|
||
"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" | ||
) | ||
|
||
// Ensure the implementation satisfies the expected interfaces. | ||
var ( | ||
_ resource.Resource = &gcpCredentialResource{} | ||
) | ||
|
||
type gcpCredentialResource struct { | ||
client *cdp.Client | ||
} | ||
|
||
func NewGcpCredentialResource() resource.Resource { | ||
return &gcpCredentialResource{} | ||
} | ||
|
||
func (r *gcpCredentialResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = req.ProviderTypeName + "_environments_gcp_credential" | ||
} | ||
|
||
func (r *gcpCredentialResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
r.client = utils.GetCdpClientForResource(req, resp) | ||
} | ||
|
||
func (r *gcpCredentialResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
// Retrieve values from data | ||
var data gcpCredentialResourceModel | ||
diags := req.Plan.Get(ctx, &data) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
dec, err := base64.StdEncoding.DecodeString(data.CredentialKey.ValueString()) | ||
|
||
if err != nil { | ||
diags.AddError("Unable to decode GCP credentials, please double check it.", | ||
"Unable to decode GCP credential due to: "+err.Error()) | ||
return | ||
} | ||
|
||
credentialKey := string(dec) | ||
|
||
params := operations.NewCreateGCPCredentialParamsWithContext(ctx) | ||
params.WithInput(&environmentsmodels.CreateGCPCredentialRequest{ | ||
CredentialName: data.CredentialName.ValueStringPointer(), | ||
Description: data.Description.ValueString(), | ||
CredentialKey: &credentialKey, | ||
}) | ||
|
||
responseOk, err := r.client.Environments.Operations.CreateGCPCredential(params) | ||
if err != nil { | ||
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "creating GCP Credential") | ||
return | ||
} | ||
|
||
data.Crn = types.StringPointerValue(responseOk.Payload.Credential.Crn) | ||
data.ID = data.Crn | ||
|
||
// Save data into Terraform state | ||
diags = resp.State.Set(ctx, data) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
} | ||
|
||
func (r *gcpCredentialResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
// Get current state | ||
var state gcpCredentialResourceModel | ||
diags := req.State.Get(ctx, &state) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
// Get refreshed value from CDP | ||
credentialName := state.CredentialName.ValueString() | ||
params := operations.NewListCredentialsParamsWithContext(ctx) | ||
params.WithInput(&environmentsmodels.ListCredentialsRequest{CredentialName: credentialName}) | ||
listCredentialsResp, err := r.client.Environments.Operations.ListCredentials(params) | ||
if err != nil { | ||
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "reading GCP Credential") | ||
return | ||
} | ||
|
||
// Overwrite items with refreshed state | ||
credentials := listCredentialsResp.GetPayload().Credentials | ||
if len(credentials) == 0 || *credentials[0].CredentialName != credentialName { | ||
resp.State.RemoveResource(ctx) // deleted | ||
return | ||
} | ||
c := credentials[0] | ||
|
||
state.ID = types.StringPointerValue(c.Crn) | ||
state.CredentialName = types.StringPointerValue(c.CredentialName) | ||
state.Crn = types.StringPointerValue(c.Crn) | ||
state.Description = types.StringValue(c.Description) | ||
|
||
// Set refreshed state | ||
diags = resp.State.Set(ctx, &state) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
} | ||
|
||
func (r *gcpCredentialResource) Update(ctx context.Context, _ resource.UpdateRequest, _ *resource.UpdateResponse) { | ||
tflog.Warn(ctx, "Update operation is not implemented yet.") | ||
} | ||
|
||
func (r *gcpCredentialResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
// Retrieve values from state | ||
var state gcpCredentialResourceModel | ||
diags := req.State.Get(ctx, &state) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
credentialName := state.CredentialName.ValueString() | ||
params := operations.NewDeleteCredentialParamsWithContext(ctx) | ||
params.WithInput(&environmentsmodels.DeleteCredentialRequest{CredentialName: &credentialName}) | ||
_, err := r.client.Environments.Operations.DeleteCredential(params) | ||
if err != nil { | ||
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "deleting GCP Credential") | ||
return | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright 2023 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/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" | ||
) | ||
|
||
func (r *gcpCredentialResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
MarkdownDescription: "The GCP credential is used for authorization to provision resources such as compute instances within your cloud provider account.", | ||
Attributes: map[string]schema.Attribute{ | ||
"id": schema.StringAttribute{ | ||
Computed: true, | ||
}, | ||
"credential_name": schema.StringAttribute{ | ||
MarkdownDescription: "The name of the CDP credential.", | ||
Required: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
"credential_key": schema.StringAttribute{ | ||
MarkdownDescription: "The GCP credential JSON content encoded in Base64", | ||
Required: true, | ||
Sensitive: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
"description": schema.StringAttribute{ | ||
Optional: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
"crn": schema.StringAttribute{ | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright 2023 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 utils | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
"os" | ||
) | ||
|
||
func ReadFileContent(ctx context.Context, path string) (*string, error) { | ||
tflog.Info(ctx, fmt.Sprintf("About to read file on path: %s", path)) | ||
data, err := os.ReadFile(path) | ||
if err != nil { | ||
tflog.Warn(ctx, fmt.Sprintf("Error occurred during file read: %s", err.Error())) | ||
return nil, err | ||
} | ||
tflog.Info(ctx, "Reading file was successful.") | ||
content := string(data) | ||
return &content, nil | ||
} |
Oops, something went wrong.