From c96e6e0be28577fb2947b313e9da7d6b825474f0 Mon Sep 17 00:00:00 2001 From: danischm Date: Tue, 31 Oct 2023 11:50:34 +0100 Subject: [PATCH] Add assign credentials resource --- docs/data-sources/assign_credentials.md | 36 +++ docs/resources/assign_credentials.md | 49 ++++ .../data-source.tf | 3 + .../import.sh | 1 + .../resource.tf | 5 + gen/definitions/assign_credentials.yaml | 80 ++++++ gen/generator.go | 1 + gen/schema/schema.yaml | 1 + gen/templates/data_source.go | 2 +- gen/templates/resource.go | 7 +- ...ource_catalystcenter_assign_credentials.go | 136 ++++++++++ ..._catalystcenter_assign_credentials_test.go | 92 +++++++ ...model_catalystcenter_assign_credentials.go | 150 +++++++++++ internal/provider/provider.go | 2 + ...ource_catalystcenter_assign_credentials.go | 246 ++++++++++++++++++ ..._catalystcenter_assign_credentials_test.go | 104 ++++++++ 16 files changed, 912 insertions(+), 3 deletions(-) create mode 100644 docs/data-sources/assign_credentials.md create mode 100644 docs/resources/assign_credentials.md create mode 100644 examples/data-sources/catalystcenter_assign_credentials/data-source.tf create mode 100644 examples/resources/catalystcenter_assign_credentials/import.sh create mode 100644 examples/resources/catalystcenter_assign_credentials/resource.tf create mode 100644 gen/definitions/assign_credentials.yaml create mode 100644 internal/provider/data_source_catalystcenter_assign_credentials.go create mode 100644 internal/provider/data_source_catalystcenter_assign_credentials_test.go create mode 100644 internal/provider/model_catalystcenter_assign_credentials.go create mode 100644 internal/provider/resource_catalystcenter_assign_credentials.go create mode 100644 internal/provider/resource_catalystcenter_assign_credentials_test.go diff --git a/docs/data-sources/assign_credentials.md b/docs/data-sources/assign_credentials.md new file mode 100644 index 00000000..c4be5127 --- /dev/null +++ b/docs/data-sources/assign_credentials.md @@ -0,0 +1,36 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "catalystcenter_assign_credentials Data Source - terraform-provider-catalystcenter" +subcategory: "Network Settings" +description: |- + This data source can read the assigned credentials of a site. +--- + +# catalystcenter_assign_credentials (Data Source) + +This data source can read the assigned credentials of a site. + +## Example Usage + +```terraform +data "catalystcenter_assign_credentials" "example" { + id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" +} +``` + + +## Schema + +### Required + +- `id` (String) The id of the object +- `site_id` (String) The site ID + +### Read-Only + +- `cli_id` (String) The ID of the CLI credentials +- `https_read` (String) The ID of the HTTPS read credentials +- `https_write` (String) The ID of the HTTPS write credentials +- `snmp_v2_read_id` (String) The ID of the SNMPv2 read credentials +- `snmp_v2_write_id` (String) The ID of the SNMPv2 write credentials +- `snmp_v3_id` (String) The ID of the SNMPv3 credentials diff --git a/docs/resources/assign_credentials.md b/docs/resources/assign_credentials.md new file mode 100644 index 00000000..23a46099 --- /dev/null +++ b/docs/resources/assign_credentials.md @@ -0,0 +1,49 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "catalystcenter_assign_credentials Resource - terraform-provider-catalystcenter" +subcategory: "Network Settings" +description: |- + This resource can manage the assigned credentials of a site. +--- + +# catalystcenter_assign_credentials (Resource) + +This resource can manage the assigned credentials of a site. + +## Example Usage + +```terraform +resource "catalystcenter_assign_credentials" "example" { + site_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" + cli_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" + https_read = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" +} +``` + + +## Schema + +### Required + +- `site_id` (String) The site ID + +### Optional + +- `cli_id` (String) The ID of the CLI credentials +- `https_read` (String) The ID of the HTTPS read credentials +- `https_write` (String) The ID of the HTTPS write credentials +- `snmp_v2_read_id` (String) The ID of the SNMPv2 read credentials +- `snmp_v2_write_id` (String) The ID of the SNMPv2 write credentials +- `snmp_v3_id` (String) The ID of the SNMPv3 credentials + +### Read-Only + +- `id` (String) The id of the object + +## Import + +Import is supported using the following syntax: + +```shell +terraform import catalystcenter_assign_credentials.example "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" +``` diff --git a/examples/data-sources/catalystcenter_assign_credentials/data-source.tf b/examples/data-sources/catalystcenter_assign_credentials/data-source.tf new file mode 100644 index 00000000..f2e1ce77 --- /dev/null +++ b/examples/data-sources/catalystcenter_assign_credentials/data-source.tf @@ -0,0 +1,3 @@ +data "catalystcenter_assign_credentials" "example" { + id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" +} diff --git a/examples/resources/catalystcenter_assign_credentials/import.sh b/examples/resources/catalystcenter_assign_credentials/import.sh new file mode 100644 index 00000000..3cd67ba6 --- /dev/null +++ b/examples/resources/catalystcenter_assign_credentials/import.sh @@ -0,0 +1 @@ +terraform import catalystcenter_assign_credentials.example "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" diff --git a/examples/resources/catalystcenter_assign_credentials/resource.tf b/examples/resources/catalystcenter_assign_credentials/resource.tf new file mode 100644 index 00000000..4b7ed199 --- /dev/null +++ b/examples/resources/catalystcenter_assign_credentials/resource.tf @@ -0,0 +1,5 @@ +resource "catalystcenter_assign_credentials" "example" { + site_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" + cli_id = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" + https_read = "5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1" +} diff --git a/gen/definitions/assign_credentials.yaml b/gen/definitions/assign_credentials.yaml new file mode 100644 index 00000000..0ea0be2c --- /dev/null +++ b/gen/definitions/assign_credentials.yaml @@ -0,0 +1,80 @@ +--- +name: Assign Credentials +rest_endpoint: /dna/intent/api/v2/credential-to-site +get_rest_endpoint: /api/v1/commonsetting/global +get_requires_id: true +post_update: true +no_delete: true +ds_description: This data source can read the assigned credentials of a site. +res_description: This resource can manage the assigned credentials of a site. +doc_category: Network Settings +attributes: + - model_name: siteId + type: String + query_param: true + id: true + description: The site ID + example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1 + test_value: catalystcenter_area.test.id + - model_name: cliId + response_data_path: 'response.#(key=\"credential.cli\").value.0.objReferences.0' + type: String + description: The ID of the CLI credentials + example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1 + test_value: catalystcenter_credentials_cli.test.id + minimum_test_value: catalystcenter_credentials_cli.test.id + - model_name: snmpV2ReadId + response_data_path: 'response.#(key=\"credential.snmp_v2_read\").value.0.objReferences.0' + type: String + description: The ID of the SNMPv2 read credentials + example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1 + exclude_test: true + - model_name: snmpV2WriteId + response_data_path: 'response.#(key=\"credential.snmp_v2_write\").value.0.objReferences.0' + type: String + description: The ID of the SNMPv2 write credentials + example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1 + exclude_test: true + - model_name: snmpV3Id + response_data_path: 'response.#(key=\"credential.snmp_v3\").value.0.objReferences.0' + type: String + description: The ID of the SNMPv3 credentials + example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1 + exclude_test: true + - model_name: httpRead + response_data_path: 'response.#(key=\"credential.http.read\").value.0.objReferences.0' + tf_name: https_read + type: String + description: The ID of the HTTPS read credentials + example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1 + test_value: catalystcenter_credentials_https_read.test.id + - model_name: httpWrite + response_data_path: 'response.#(key=\"credential.http.write\").value.0.objReferences.0' + tf_name: https_write + type: String + description: The ID of the HTTPS write credentials + example: 5e6f7b3a-2b0b-4a7d-8b1c-0d4b1cd5e1b1 + exclude_test: true + +test_prerequisites: | + resource "catalystcenter_area" "test" { + name = "Area1" + parent_name = "Global" + depends_on = [ + catalystcenter_credentials_cli.test, + catalystcenter_credentials_https_read.test, + ] + } + + resource "catalystcenter_credentials_cli" "test" { + description = "TestCli1" + username = "user1" + password = "password1" + } + + resource "catalystcenter_credentials_https_read" "test" { + description = "TestHttpsRead1" + username = "user1" + password = "password1" + } + \ No newline at end of file diff --git a/gen/generator.go b/gen/generator.go index 06853587..25a0b1e9 100644 --- a/gen/generator.go +++ b/gen/generator.go @@ -99,6 +99,7 @@ type YamlConfig struct { GetRestEndpoint string `yaml:"get_rest_endpoint"` GetNoId bool `yaml:"get_no_id"` GetFromAll bool `yaml:"get_from_all"` + GetRequiresId bool `yaml:"get_requires_id"` NoDelete bool `yaml:"no_delete"` PostUpdate bool `yaml:"post_update"` RootList bool `yaml:"root_list"` diff --git a/gen/schema/schema.yaml b/gen/schema/schema.yaml index ea4cf69e..bf0c4699 100644 --- a/gen/schema/schema.yaml +++ b/gen/schema/schema.yaml @@ -4,6 +4,7 @@ rest_endpoint: str() # REST endpoint path get_rest_endpoint: str(required=False) # Override GET REST endpoint path get_no_id: bool(required=False) # Set to true if the GET request does not require an ID get_from_all: bool(required=False) # Set to true if GET does not support querying individual objects +get_requires_id: bool(required=False) # Set to true if the GET request requires an ID in the URL path no_delete: bool(required=False) # Set to true if the DELETE request is not supported post_update: bool(required=False) # Set to true if the POST request is used for update root_list: bool(required=False) # Set to true if the root element of the data structure is a list diff --git a/gen/templates/data_source.go b/gen/templates/data_source.go index 5a233887..32bf547b 100644 --- a/gen/templates/data_source.go +++ b/gen/templates/data_source.go @@ -207,7 +207,7 @@ func (d *{{camelCase .Name}}DataSource) Read(ctx context.Context, req datasource params := "" {{- if .IdQueryParam}} params += "?{{.IdQueryParam}}=" + config.Id.ValueString() - {{- else if hasQueryParam .Attributes}} + {{- else if and (hasQueryParam .Attributes) (not .GetRequiresId)}} {{- $queryParam := getQueryParam .Attributes}} params += "?{{$queryParam.ModelName}}=" + config.{{toGoName $queryParam.TfName}}.Value{{$queryParam.Type}}() {{- else if and (not .GetNoId) (not .GetFromAll)}} diff --git a/gen/templates/resource.go b/gen/templates/resource.go index 062fe9a2..1f8cac7e 100644 --- a/gen/templates/resource.go +++ b/gen/templates/resource.go @@ -411,7 +411,7 @@ func (r *{{camelCase .Name}}Resource) Create(ctx context.Context, req resource.C {{- if .IdPath}} plan.Id = types.StringValue(res.Get("{{.IdPath}}").String()) {{- else if .IdFromQueryPath}} - {{- $id := getId .Attributes}} + {{- $id := getId .Attributes}} params = "" {{- if hasQueryParam .Attributes}} {{- $queryParam := getQueryParam .Attributes}} @@ -423,6 +423,9 @@ func (r *{{camelCase .Name}}Resource) Create(ctx context.Context, req resource.C return } plan.Id = types.StringValue(res.Get("{{.IdFromQueryPath}}.#({{if $id.ResponseModelName}}{{$id.ResponseModelName}}{{else}}{{$id.ModelName}}{{end}}==\""+ plan.{{toGoName $id.TfName}}.Value{{$id.Type}}() +"\").id").String()) + {{- else if hasId .Attributes}} + {{- $id := getId .Attributes}} + plan.Id = types.StringValue(fmt.Sprint(plan.{{toGoName $id.TfName}}.Value{{$id.Type}}())) {{- end}} tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString())) @@ -448,7 +451,7 @@ func (r *{{camelCase .Name}}Resource) Read(ctx context.Context, req resource.Rea params := "" {{- if .IdQueryParam}} params += "?{{.IdQueryParam}}=" + state.Id.ValueString() - {{- else if hasQueryParam .Attributes}} + {{- else if and (hasQueryParam .Attributes) (not .GetRequiresId)}} {{- $queryParam := getQueryParam .Attributes}} params += "?{{$queryParam.ModelName}}=" + state.{{toGoName $queryParam.TfName}}.Value{{$queryParam.Type}}() {{- else if and (not .GetNoId) (not .GetFromAll)}} diff --git a/internal/provider/data_source_catalystcenter_assign_credentials.go b/internal/provider/data_source_catalystcenter_assign_credentials.go new file mode 100644 index 00000000..a126c174 --- /dev/null +++ b/internal/provider/data_source_catalystcenter_assign_credentials.go @@ -0,0 +1,136 @@ +// Copyright © 2023 Cisco Systems, Inc. and its affiliates. +// All rights reserved. +// +// Licensed under the Mozilla Public 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 +// +// https://mozilla.org/MPL/2.0/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by "gen/generator.go"; DO NOT EDIT. + +package provider + +//template:begin imports +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-log/tflog" + cc "github.com/netascode/go-catalystcenter" +) + +//template:end imports + +//template:begin model + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ datasource.DataSource = &AssignCredentialsDataSource{} + _ datasource.DataSourceWithConfigure = &AssignCredentialsDataSource{} +) + +func NewAssignCredentialsDataSource() datasource.DataSource { + return &AssignCredentialsDataSource{} +} + +type AssignCredentialsDataSource struct { + client *cc.Client +} + +func (d *AssignCredentialsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_assign_credentials" +} + +func (d *AssignCredentialsDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "This data source can read the assigned credentials of a site.", + + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + MarkdownDescription: "The id of the object", + Required: true, + }, + "site_id": schema.StringAttribute{ + MarkdownDescription: "The site ID", + Required: true, + }, + "cli_id": schema.StringAttribute{ + MarkdownDescription: "The ID of the CLI credentials", + Computed: true, + }, + "snmp_v2_read_id": schema.StringAttribute{ + MarkdownDescription: "The ID of the SNMPv2 read credentials", + Computed: true, + }, + "snmp_v2_write_id": schema.StringAttribute{ + MarkdownDescription: "The ID of the SNMPv2 write credentials", + Computed: true, + }, + "snmp_v3_id": schema.StringAttribute{ + MarkdownDescription: "The ID of the SNMPv3 credentials", + Computed: true, + }, + "https_read": schema.StringAttribute{ + MarkdownDescription: "The ID of the HTTPS read credentials", + Computed: true, + }, + "https_write": schema.StringAttribute{ + MarkdownDescription: "The ID of the HTTPS write credentials", + Computed: true, + }, + }, + } +} + +func (d *AssignCredentialsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + d.client = req.ProviderData.(*CcProviderData).Client +} + +//template:end model + +//template:begin read +func (d *AssignCredentialsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var config AssignCredentials + + // Read config + diags := req.Config.Get(ctx, &config) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String())) + + params := "" + params += "/" + config.Id.ValueString() + res, err := d.client.Get("/api/v1/commonsetting/global" + params) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object, got error: %s", err)) + return + } + + config.fromBody(ctx, res) + + tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", config.Id.ValueString())) + + diags = resp.State.Set(ctx, &config) + resp.Diagnostics.Append(diags...) +} + +//template:end read diff --git a/internal/provider/data_source_catalystcenter_assign_credentials_test.go b/internal/provider/data_source_catalystcenter_assign_credentials_test.go new file mode 100644 index 00000000..0e65056d --- /dev/null +++ b/internal/provider/data_source_catalystcenter_assign_credentials_test.go @@ -0,0 +1,92 @@ +// Copyright © 2023 Cisco Systems, Inc. and its affiliates. +// All rights reserved. +// +// Licensed under the Mozilla Public 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 +// +// https://mozilla.org/MPL/2.0/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by "gen/generator.go"; DO NOT EDIT. + +package provider + +//template:begin imports +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +//template:end imports + +//template:begin testAccDataSource +func TestAccDataSourceCcAssignCredentials(t *testing.T) { + var checks []resource.TestCheckFunc + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceCcAssignCredentialsPrerequisitesConfig + testAccDataSourceCcAssignCredentialsConfig(), + Check: resource.ComposeTestCheckFunc(checks...), + }, + }, + }) +} + +//template:end testAccDataSource + +//template:begin testPrerequisites +const testAccDataSourceCcAssignCredentialsPrerequisitesConfig = ` +resource "catalystcenter_area" "test" { + name = "Area1" + parent_name = "Global" + depends_on = [ + catalystcenter_credentials_cli.test, + catalystcenter_credentials_https_read.test, + ] +} + +resource "catalystcenter_credentials_cli" "test" { + description = "TestCli1" + username = "user1" + password = "password1" +} + +resource "catalystcenter_credentials_https_read" "test" { + description = "TestHttpsRead1" + username = "user1" + password = "password1" +} + +` + +//template:end testPrerequisites + +//template:begin testAccDataSourceConfig +func testAccDataSourceCcAssignCredentialsConfig() string { + config := `resource "catalystcenter_assign_credentials" "test" {` + "\n" + config += ` site_id = catalystcenter_area.test.id` + "\n" + config += ` cli_id = catalystcenter_credentials_cli.test.id` + "\n" + config += ` https_read = catalystcenter_credentials_https_read.test.id` + "\n" + config += `}` + "\n" + + config += ` + data "catalystcenter_assign_credentials" "test" { + id = catalystcenter_assign_credentials.test.id + site_id = catalystcenter_area.test.id + } + ` + return config +} + +//template:end testAccDataSourceConfig diff --git a/internal/provider/model_catalystcenter_assign_credentials.go b/internal/provider/model_catalystcenter_assign_credentials.go new file mode 100644 index 00000000..5e0fe768 --- /dev/null +++ b/internal/provider/model_catalystcenter_assign_credentials.go @@ -0,0 +1,150 @@ +// Copyright © 2023 Cisco Systems, Inc. and its affiliates. +// All rights reserved. +// +// Licensed under the Mozilla Public 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 +// +// https://mozilla.org/MPL/2.0/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by "gen/generator.go"; DO NOT EDIT. + +package provider + +//template:begin imports +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +//template:end imports + +//template:begin types +type AssignCredentials struct { + Id types.String `tfsdk:"id"` + SiteId types.String `tfsdk:"site_id"` + CliId types.String `tfsdk:"cli_id"` + SnmpV2ReadId types.String `tfsdk:"snmp_v2_read_id"` + SnmpV2WriteId types.String `tfsdk:"snmp_v2_write_id"` + SnmpV3Id types.String `tfsdk:"snmp_v3_id"` + HttpsRead types.String `tfsdk:"https_read"` + HttpsWrite types.String `tfsdk:"https_write"` +} + +//template:end types + +//template:begin getPath +func (data AssignCredentials) getPath() string { + return "/dna/intent/api/v2/credential-to-site" +} + +//template:end getPath + +//template:begin toBody +func (data AssignCredentials) toBody(ctx context.Context, state AssignCredentials) string { + body := "" + if !data.CliId.IsNull() { + body, _ = sjson.Set(body, "cliId", data.CliId.ValueString()) + } + if !data.SnmpV2ReadId.IsNull() { + body, _ = sjson.Set(body, "snmpV2ReadId", data.SnmpV2ReadId.ValueString()) + } + if !data.SnmpV2WriteId.IsNull() { + body, _ = sjson.Set(body, "snmpV2WriteId", data.SnmpV2WriteId.ValueString()) + } + if !data.SnmpV3Id.IsNull() { + body, _ = sjson.Set(body, "snmpV3Id", data.SnmpV3Id.ValueString()) + } + if !data.HttpsRead.IsNull() { + body, _ = sjson.Set(body, "httpRead", data.HttpsRead.ValueString()) + } + if !data.HttpsWrite.IsNull() { + body, _ = sjson.Set(body, "httpWrite", data.HttpsWrite.ValueString()) + } + return body +} + +//template:end toBody + +//template:begin fromBody +func (data *AssignCredentials) fromBody(ctx context.Context, res gjson.Result) { + if value := res.Get("response.#(key=\"credential.cli\").value.0.objReferences.0"); value.Exists() { + data.CliId = types.StringValue(value.String()) + } else { + data.CliId = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.snmp_v2_read\").value.0.objReferences.0"); value.Exists() { + data.SnmpV2ReadId = types.StringValue(value.String()) + } else { + data.SnmpV2ReadId = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.snmp_v2_write\").value.0.objReferences.0"); value.Exists() { + data.SnmpV2WriteId = types.StringValue(value.String()) + } else { + data.SnmpV2WriteId = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.snmp_v3\").value.0.objReferences.0"); value.Exists() { + data.SnmpV3Id = types.StringValue(value.String()) + } else { + data.SnmpV3Id = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.http.read\").value.0.objReferences.0"); value.Exists() { + data.HttpsRead = types.StringValue(value.String()) + } else { + data.HttpsRead = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.http.write\").value.0.objReferences.0"); value.Exists() { + data.HttpsWrite = types.StringValue(value.String()) + } else { + data.HttpsWrite = types.StringNull() + } +} + +//template:end fromBody + +//template:begin updateFromBody +func (data *AssignCredentials) updateFromBody(ctx context.Context, res gjson.Result) { + if value := res.Get("response.#(key=\"credential.cli\").value.0.objReferences.0"); value.Exists() && !data.CliId.IsNull() { + data.CliId = types.StringValue(value.String()) + } else { + data.CliId = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.snmp_v2_read\").value.0.objReferences.0"); value.Exists() && !data.SnmpV2ReadId.IsNull() { + data.SnmpV2ReadId = types.StringValue(value.String()) + } else { + data.SnmpV2ReadId = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.snmp_v2_write\").value.0.objReferences.0"); value.Exists() && !data.SnmpV2WriteId.IsNull() { + data.SnmpV2WriteId = types.StringValue(value.String()) + } else { + data.SnmpV2WriteId = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.snmp_v3\").value.0.objReferences.0"); value.Exists() && !data.SnmpV3Id.IsNull() { + data.SnmpV3Id = types.StringValue(value.String()) + } else { + data.SnmpV3Id = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.http.read\").value.0.objReferences.0"); value.Exists() && !data.HttpsRead.IsNull() { + data.HttpsRead = types.StringValue(value.String()) + } else { + data.HttpsRead = types.StringNull() + } + if value := res.Get("response.#(key=\"credential.http.write\").value.0.objReferences.0"); value.Exists() && !data.HttpsWrite.IsNull() { + data.HttpsWrite = types.StringValue(value.String()) + } else { + data.HttpsWrite = types.StringNull() + } +} + +//template:end updateFromBody diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 5c01940a..aac94f5c 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -241,6 +241,7 @@ func (p *CcProvider) Configure(ctx context.Context, req provider.ConfigureReques func (p *CcProvider) Resources(ctx context.Context) []func() resource.Resource { return []func() resource.Resource{ NewAreaResource, + NewAssignCredentialsResource, NewBuildingResource, NewCredentialsCLIResource, NewCredentialsHTTPSReadResource, @@ -257,6 +258,7 @@ func (p *CcProvider) Resources(ctx context.Context) []func() resource.Resource { func (p *CcProvider) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ NewAreaDataSource, + NewAssignCredentialsDataSource, NewBuildingDataSource, NewCredentialsCLIDataSource, NewCredentialsHTTPSReadDataSource, diff --git a/internal/provider/resource_catalystcenter_assign_credentials.go b/internal/provider/resource_catalystcenter_assign_credentials.go new file mode 100644 index 00000000..620d9738 --- /dev/null +++ b/internal/provider/resource_catalystcenter_assign_credentials.go @@ -0,0 +1,246 @@ +// Copyright © 2023 Cisco Systems, Inc. and its affiliates. +// All rights reserved. +// +// Licensed under the Mozilla Public 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 +// +// https://mozilla.org/MPL/2.0/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by "gen/generator.go"; DO NOT EDIT. + +package provider + +//template:begin imports +import ( + "context" + "fmt" + "strings" + + "github.com/CiscoDevNet/terraform-provider-catalystcenter/internal/provider/helpers" + "github.com/hashicorp/terraform-plugin-framework/path" + "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" + cc "github.com/netascode/go-catalystcenter" +) + +//template:end imports + +//template:begin model + +// Ensure provider defined types fully satisfy framework interfaces +var _ resource.Resource = &AssignCredentialsResource{} +var _ resource.ResourceWithImportState = &AssignCredentialsResource{} + +func NewAssignCredentialsResource() resource.Resource { + return &AssignCredentialsResource{} +} + +type AssignCredentialsResource struct { + client *cc.Client +} + +func (r *AssignCredentialsResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_assign_credentials" +} + +func (r *AssignCredentialsResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: helpers.NewAttributeDescription("This resource can manage the assigned credentials of a site.").String, + + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + MarkdownDescription: "The id of the object", + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "site_id": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The site ID").String, + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "cli_id": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The ID of the CLI credentials").String, + Optional: true, + }, + "snmp_v2_read_id": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The ID of the SNMPv2 read credentials").String, + Optional: true, + }, + "snmp_v2_write_id": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The ID of the SNMPv2 write credentials").String, + Optional: true, + }, + "snmp_v3_id": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The ID of the SNMPv3 credentials").String, + Optional: true, + }, + "https_read": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The ID of the HTTPS read credentials").String, + Optional: true, + }, + "https_write": schema.StringAttribute{ + MarkdownDescription: helpers.NewAttributeDescription("The ID of the HTTPS write credentials").String, + Optional: true, + }, + }, + } +} + +func (r *AssignCredentialsResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + r.client = req.ProviderData.(*CcProviderData).Client +} + +//template:end model + +//template:begin create +func (r *AssignCredentialsResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan AssignCredentials + + // Read plan + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Create", plan.Id.ValueString())) + + // Create object + body := plan.toBody(ctx, AssignCredentials{}) + + params := "" + params += "/" + plan.SiteId.ValueString() + res, err := r.client.Post(plan.getPath()+params, body) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (POST), got error: %s, %s", err, res.String())) + return + } + plan.Id = types.StringValue(fmt.Sprint(plan.SiteId.ValueString())) + + tflog.Debug(ctx, fmt.Sprintf("%s: Create finished successfully", plan.Id.ValueString())) + + diags = resp.State.Set(ctx, &plan) + resp.Diagnostics.Append(diags...) +} + +//template:end create + +//template:begin read +func (r *AssignCredentialsResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state AssignCredentials + + // Read state + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", state.Id.String())) + + params := "" + params += "/" + state.Id.ValueString() + res, err := r.client.Get("/api/v1/commonsetting/global" + params) + if err != nil && strings.Contains(err.Error(), "StatusCode 404") { + resp.State.RemoveResource(ctx) + return + } else if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to retrieve object (GET), got error: %s, %s", err, res.String())) + return + } + + state.updateFromBody(ctx, res) + + tflog.Debug(ctx, fmt.Sprintf("%s: Read finished successfully", state.Id.ValueString())) + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) +} + +//template:end read + +//template:begin update +func (r *AssignCredentialsResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan, state AssignCredentials + + // Read plan + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + // Read state + diags = req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Update", plan.Id.ValueString())) + + body := plan.toBody(ctx, state) + params := "" + params += "/" + plan.SiteId.ValueString() + + res, err := r.client.Post(plan.getPath()+params, body) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Failed to configure object (PUT), got error: %s, %s", err, res.String())) + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Update finished successfully", plan.Id.ValueString())) + + diags = resp.State.Set(ctx, &plan) + resp.Diagnostics.Append(diags...) +} + +//template:end update + +//template:begin delete +func (r *AssignCredentialsResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state AssignCredentials + + // Read state + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Delete", state.Id.ValueString())) + + tflog.Debug(ctx, fmt.Sprintf("%s: Delete finished successfully", state.Id.ValueString())) + + resp.State.RemoveResource(ctx) +} + +//template:end delete + +//template:begin import +func (r *AssignCredentialsResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +//template:end import diff --git a/internal/provider/resource_catalystcenter_assign_credentials_test.go b/internal/provider/resource_catalystcenter_assign_credentials_test.go new file mode 100644 index 00000000..5eec9df4 --- /dev/null +++ b/internal/provider/resource_catalystcenter_assign_credentials_test.go @@ -0,0 +1,104 @@ +// Copyright © 2023 Cisco Systems, Inc. and its affiliates. +// All rights reserved. +// +// Licensed under the Mozilla Public 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 +// +// https://mozilla.org/MPL/2.0/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: MPL-2.0 + +// Code generated by "gen/generator.go"; DO NOT EDIT. + +package provider + +//template:begin imports +import ( + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +//template:end imports + +//template:begin testAcc +func TestAccCcAssignCredentials(t *testing.T) { + var checks []resource.TestCheckFunc + + var steps []resource.TestStep + if os.Getenv("SKIP_MINIMUM_TEST") == "" { + steps = append(steps, resource.TestStep{ + Config: testAccCcAssignCredentialsPrerequisitesConfig + testAccCcAssignCredentialsConfig_minimum(), + }) + } + steps = append(steps, resource.TestStep{ + Config: testAccCcAssignCredentialsPrerequisitesConfig + testAccCcAssignCredentialsConfig_all(), + Check: resource.ComposeTestCheckFunc(checks...), + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: steps, + }) +} + +//template:end testAcc + +//template:begin testPrerequisites +const testAccCcAssignCredentialsPrerequisitesConfig = ` +resource "catalystcenter_area" "test" { + name = "Area1" + parent_name = "Global" + depends_on = [ + catalystcenter_credentials_cli.test, + catalystcenter_credentials_https_read.test, + ] +} + +resource "catalystcenter_credentials_cli" "test" { + description = "TestCli1" + username = "user1" + password = "password1" +} + +resource "catalystcenter_credentials_https_read" "test" { + description = "TestHttpsRead1" + username = "user1" + password = "password1" +} + +` + +//template:end testPrerequisites + +//template:begin testAccConfigMinimal +func testAccCcAssignCredentialsConfig_minimum() string { + config := `resource "catalystcenter_assign_credentials" "test" {` + "\n" + config += ` site_id = catalystcenter_area.test.id` + "\n" + config += ` cli_id = catalystcenter_credentials_cli.test.id` + "\n" + config += `}` + "\n" + return config +} + +//template:end testAccConfigMinimal + +//template:begin testAccConfigAll +func testAccCcAssignCredentialsConfig_all() string { + config := `resource "catalystcenter_assign_credentials" "test" {` + "\n" + config += ` site_id = catalystcenter_area.test.id` + "\n" + config += ` cli_id = catalystcenter_credentials_cli.test.id` + "\n" + config += ` https_read = catalystcenter_credentials_https_read.test.id` + "\n" + config += `}` + "\n" + return config +} + +//template:end testAccConfigAll