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

add fmc_deploy #210

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
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
39 changes: 39 additions & 0 deletions docs/resources/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "fmc_deployment Resource - terraform-provider-fmc"
subcategory: "Deployment"
description: |-
This resource can manage a Deployment.
---

# fmc_deployment (Resource)

This resource can manage a Deployment.

## Example Usage

```terraform
resource "fmc_deployment" "example" {
device_list = ["2fe9063e-8bd5-11ef-9475-e4aeac78cf37"]
deployment_note = "Deployment note"
}
```

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

### Required

- `device_list` (List of String) List of device ids to be deployed. If forceDeploy is not set to true, only devices that are deployable will be deployed.

### Optional

- `deploy` (Boolean) This attribute is only used internally.
- `deployment_note` (String) User note related to deployment.
- `domain` (String) The name of the FMC domain
- `force_deploy` (Boolean) Force deployment (even if there are no configuration changes).
- `version` (String) Version to which the deployment should be done. By default set to current unix timestamp.

### Read-Only

- `id` (String) The id of the object
3 changes: 3 additions & 0 deletions examples/data-sources/fmc_deployment/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data "fmc_deployment" "example" {
id = "76d24097-41c4-4558-a4d0-a8c07ac08470"
}
4 changes: 4 additions & 0 deletions examples/resources/fmc_deployment/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resource "fmc_deployment" "example" {
device_list = ["2fe9063e-8bd5-11ef-9475-e4aeac78cf37"]
deployment_note = "Deployment note"
}
46 changes: 46 additions & 0 deletions gen/definitions/deploy_device.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
name: Deployment
rest_endpoint: /api/fmc_config/v1/domain/{DOMAIN_UUID}/deployment/deploymentrequests
no_data_source: true
no_import: true
no_delete: true
doc_category: Deployment
test_tags: [TF_VAR_timestamp, TF_VAR_device_id_list]
attributes:
- model_name: type
type: String
value: "DeploymentRequest"
- model_name: version
type: String
description: Version to which the deployment should be done. By default set to current unix timestamp.
exclude_example: true
- model_name: forceDeploy
type: Bool
description: Force deployment (even if there are no configuration changes).
exclude_example: true
exclude_test: true
- model_name: ignoreWarning
type: Bool
value: "true"
- model_name: deviceList
type: List
description: List of device ids to be deployed. If forceDeploy is not set to true, only devices that are deployable will be deployed.
mandatory: true
element_type: String
example: 2fe9063e-8bd5-11ef-9475-e4aeac78cf37
test_value: var.device_id_list
- model_name: deploymentNote
type: String
description: User note related to deployment.
example: "Deployment note"
exclude_test: true
- model_name: deploy
description: "This attribute is only used internally"
type: Bool
exclude_test: true
exclude_example: true
# test_prerequisites: |-
# variable "device_id_list" { // tests will set $TF_VAR_device_id_list
# type = list(string)
# default = null
# }
138 changes: 138 additions & 0 deletions internal/provider/data_source_fmc_deployment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// 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

package provider

// Section below is generated&owned by "gen/generator.go". //template:begin imports
import (
"context"
"fmt"
"net/url"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/netascode/go-fmc"
)

// End of section. //template:end imports

// Section below is generated&owned by "gen/generator.go". //template:begin model

// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &DeploymentDataSource{}
_ datasource.DataSourceWithConfigure = &DeploymentDataSource{}
)

func NewDeploymentDataSource() datasource.DataSource {
return &DeploymentDataSource{}
}

type DeploymentDataSource struct {
client *fmc.Client
}

func (d *DeploymentDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_deployment"
}

func (d *DeploymentDataSource) 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 Deployment.",

Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
MarkdownDescription: "The id of the object",
Required: true,
},
"domain": schema.StringAttribute{
MarkdownDescription: "The name of the FMC domain",
Optional: true,
},
"version": schema.StringAttribute{
MarkdownDescription: "Epoch unix time stamp (13 digits).",
Computed: true,
},
"force_deploy": schema.BoolAttribute{
MarkdownDescription: "Force deployment (even if there are no configuration changes).",
Computed: true,
},
"ignore_warning": schema.BoolAttribute{
MarkdownDescription: "Ignore warnings during deployment.",
Computed: true,
},
"device_list": schema.SetAttribute{
MarkdownDescription: "List of device ids to be deployed.",
ElementType: types.StringType,
Computed: true,
},
"deployment_note": schema.StringAttribute{
MarkdownDescription: "User note related to deployment.",
Computed: true,
},
},
}
}

func (d *DeploymentDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

d.client = req.ProviderData.(*FmcProviderData).Client
}

// End of section. //template:end model

// Section below is generated&owned by "gen/generator.go". //template:begin read

func (d *DeploymentDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var config Deployment

// Read config
diags := req.Config.Get(ctx, &config)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

// Set request domain if provided
reqMods := [](func(*fmc.Req)){}
if !config.Domain.IsNull() && config.Domain.ValueString() != "" {
reqMods = append(reqMods, fmc.DomainName(config.Domain.ValueString()))
}

tflog.Debug(ctx, fmt.Sprintf("%s: Beginning Read", config.Id.String()))
urlPath := config.getPath() + "/" + url.QueryEscape(config.Id.ValueString())
res, err := d.client.Get(urlPath, reqMods...)
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...)
}

// End of section. //template:end read
80 changes: 80 additions & 0 deletions internal/provider/data_source_fmc_deployment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 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

package provider

// Section below is generated&owned by "gen/generator.go". //template:begin imports
import (
"os"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

// End of section. //template:end imports

// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSource

func TestAccDataSourceFmcDeployment(t *testing.T) {
if os.Getenv("TF_VAR_timestamp") == "" && os.Getenv("TF_VAR_device_id_list") == "" {
t.Skip("skipping test, set environment variable TF_VAR_timestamp or TF_VAR_device_id_list")
}
var checks []resource.TestCheckFunc
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccDataSourceFmcDeploymentPrerequisitesConfig + testAccDataSourceFmcDeploymentConfig(),
Check: resource.ComposeTestCheckFunc(checks...),
},
},
})
}

// End of section. //template:end testAccDataSource

// Section below is generated&owned by "gen/generator.go". //template:begin testPrerequisites

const testAccDataSourceFmcDeploymentPrerequisitesConfig = `
variable "timestamp" { default = null } // tests will set $TF_VAR_timestamp
variable "device_id_list" { // tests will set $TF_VAR_device_id_list
type = list(string)
default = null
}
`

// End of section. //template:end testPrerequisites

// Section below is generated&owned by "gen/generator.go". //template:begin testAccDataSourceConfig

func testAccDataSourceFmcDeploymentConfig() string {
config := `resource "fmc_deployment" "test" {` + "\n"
config += ` version = var.timestamp` + "\n"
config += ` ignore_warning = true` + "\n"
config += ` device_list = var.device_id_list` + "\n"
config += `}` + "\n"

config += `
data "fmc_deployment" "test" {
id = fmc_deployment.test.id
}
`
return config
}

// End of section. //template:end testAccDataSourceConfig
8 changes: 8 additions & 0 deletions internal/provider/helpers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ func GetStringList(result []gjson.Result) types.List {
return types.ListValueMust(types.StringType, v)
}

func GetStringListFromStringSlice(result []string) types.List {
v := make([]attr.Value, len(result))
for i, e := range result {
v[i] = types.StringValue(e)
}
return types.ListValueMust(types.StringType, v)
}

func GetInt64List(result []gjson.Result) types.List {
v := make([]attr.Value, len(result))
for r := range result {
Expand Down
Loading
Loading