Skip to content

Commit

Permalink
Merge pull request #781 from Juniper/bug/780-freeform-external-system…
Browse files Browse the repository at this point in the history
…-no-device-profile-id

`freeform_system` resource: support optional `device_profile_id` when `type` is `external`
  • Loading branch information
chrismarget-j authored Aug 13, 2024
2 parents 9132d0e + b70cb25 commit 22a2428
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 26 deletions.
36 changes: 25 additions & 11 deletions apstra/freeform/freeform_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"regexp"

"github.com/Juniper/apstra-go-sdk/apstra"
apstravalidator "github.com/Juniper/terraform-provider-apstra/apstra/apstra_validator"
"github.com/Juniper/terraform-provider-apstra/apstra/utils"
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
Expand Down Expand Up @@ -103,7 +104,8 @@ func (o FreeformSystem) ResourceAttributes() map[string]resourceSchema.Attribute
MarkdownDescription: "Freeform System name as shown in the Web UI.",
Required: true,
Validators: []validator.String{
stringvalidator.RegexMatches(regexp.MustCompile("^[a-zA-Z0-9.-_]+$"), "name may consist only of the following characters : a-zA-Z0-9.-_")},
stringvalidator.RegexMatches(regexp.MustCompile("^[a-zA-Z0-9.-_]+$"), "name may consist only of the following characters : a-zA-Z0-9.-_"),
},
},
"hostname": resourceSchema.StringAttribute{
MarkdownDescription: "Hostname of the Freeform System.",
Expand All @@ -118,15 +120,26 @@ func (o FreeformSystem) ResourceAttributes() map[string]resourceSchema.Attribute
Validators: []validator.String{stringvalidator.OneOf(utils.AllNodeDeployModes()...)},
},
"type": resourceSchema.StringAttribute{
MarkdownDescription: fmt.Sprintf("Type of the System. Must be one of `%s` or `%s`", apstra.SystemTypeInternal, apstra.SystemTypeExternal),
Required: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Validators: []validator.String{stringvalidator.OneOf(apstra.SystemTypeInternal.String(), apstra.SystemTypeExternal.String())},
MarkdownDescription: fmt.Sprintf("Type of the System. Must be one of `%s` or `%s`",
utils.StringersToFriendlyString(apstra.SystemTypeInternal),
utils.StringersToFriendlyString(apstra.SystemTypeExternal),
),
Required: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Validators: []validator.String{stringvalidator.OneOf(
utils.StringersToFriendlyString(apstra.SystemTypeInternal),
utils.StringersToFriendlyString(apstra.SystemTypeExternal),
)},
},
"device_profile_id": resourceSchema.StringAttribute{
MarkdownDescription: "Device profile ID of the System",
Optional: true,
Validators: []validator.String{stringvalidator.LengthAtLeast(1)},
MarkdownDescription: fmt.Sprintf("Device profile ID of the System. Required when `type` is %q.",
utils.StringersToFriendlyString(apstra.SystemTypeInternal)),
Optional: true,
Validators: []validator.String{
stringvalidator.LengthAtLeast(1),
apstravalidator.ForbiddenWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.SystemTypeExternal))),
apstravalidator.RequiredWhenValueIs(path.MatchRoot("type"), types.StringValue(utils.StringersToFriendlyString(apstra.SystemTypeInternal))),
},
},
"system_id": resourceSchema.StringAttribute{
MarkdownDescription: "ID (usually serial number) of the Managed Device to associate with this System",
Expand All @@ -151,9 +164,9 @@ func (o *FreeformSystem) Request(ctx context.Context, diags *diag.Diagnostics) *

var systemType apstra.SystemType
switch o.Type.ValueString() {
case apstra.SystemTypeExternal.String():
case utils.StringersToFriendlyString(apstra.SystemTypeExternal):
systemType = apstra.SystemTypeExternal
case apstra.SystemTypeInternal.String():
case utils.StringersToFriendlyString(apstra.SystemTypeInternal):
systemType = apstra.SystemTypeInternal
default:
diags.AddError("unexpected system type", "got: "+o.Type.ValueString())
Expand All @@ -172,8 +185,9 @@ func (o *FreeformSystem) Request(ctx context.Context, diags *diag.Diagnostics) *
func (o *FreeformSystem) LoadApiData(ctx context.Context, in *apstra.FreeformSystemData, diags *diag.Diagnostics) {
o.Name = types.StringValue(in.Label)
o.Hostname = types.StringValue(in.Hostname)
o.Type = types.StringValue(in.Type.String())
o.Type = types.StringValue(utils.StringersToFriendlyString(in.Type))
o.DeviceProfileId = types.StringValue(string(in.DeviceProfileId))
o.DeviceProfileId = utils.StringValueOrNull(ctx, in.DeviceProfileId.String(), diags)
o.SystemId = types.StringPointerValue((*string)(in.SystemId))
o.Tags = utils.SetValueOrNull(ctx, types.StringType, in.Tags, diags) // safe to ignore diagnostic here
}
87 changes: 76 additions & 11 deletions apstra/resource_freeform_system_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ package tfapstra_test
import (
"context"
"fmt"
"github.com/Juniper/apstra-go-sdk/apstra"
"math/rand"
"strconv"
"testing"

"github.com/Juniper/apstra-go-sdk/apstra"
tfapstra "github.com/Juniper/terraform-provider-apstra/apstra"
testutils "github.com/Juniper/terraform-provider-apstra/apstra/test_utils"
"github.com/hashicorp/go-version"
Expand All @@ -22,7 +22,7 @@ const (
resource %q %q {
blueprint_id = %q
name = %q
device_profile_id = %q
device_profile_id = %s
hostname = %q
type = %q
deploy_mode = %s
Expand All @@ -46,7 +46,7 @@ func (o resourceFreeformSystem) render(rType, rName string) string {
rType, rName,
o.blueprintId,
o.name,
o.deviceProfileId,
stringOrNull(o.deviceProfileId),
o.hostname,
o.systemType,
stringOrNull(o.deployMode),
Expand All @@ -62,7 +62,11 @@ func (o resourceFreeformSystem) testChecks(t testing.TB, rType, rName string) te
result.append(t, "TestCheckResourceAttr", "blueprint_id", o.blueprintId)
result.append(t, "TestCheckResourceAttr", "name", o.name)
result.append(t, "TestCheckResourceAttr", "type", o.systemType)
result.append(t, "TestCheckResourceAttr", "device_profile_id", o.deviceProfileId)
if o.deviceProfileId != "" {
result.append(t, "TestCheckResourceAttr", "device_profile_id", o.deviceProfileId)
} else {
result.append(t, "TestCheckNoResourceAttr", "device_profile_id")
}
result.append(t, "TestCheckResourceAttr", "hostname", o.hostname)
if o.deployMode != "" {
result.append(t, "TestCheckResourceAttr", "deploy_mode", o.deployMode)
Expand All @@ -84,7 +88,8 @@ func TestResourceFreeformSystem(t *testing.T) {

// create a blueprint
bp := testutils.FfBlueprintA(t, ctx)
// get a device profile

// import a device profile
dpId, _ := bp.ImportDeviceProfile(ctx, "Juniper_vEX")

type testStep struct {
Expand All @@ -96,7 +101,69 @@ func TestResourceFreeformSystem(t *testing.T) {
}

testCases := map[string]testCase{
"start_with_no_tags": {
"external_start_minimal": {
steps: []testStep{
{
config: resourceFreeformSystem{
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
systemType: apstra.SystemTypeExternal.String(),
},
},
{
config: resourceFreeformSystem{
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
deployMode: apstra.DeployModeDeploy.String(),
systemType: apstra.SystemTypeExternal.String(),
tags: randomStrings(rand.Intn(10)+2, 6),
},
},
{
config: resourceFreeformSystem{
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
systemType: apstra.SystemTypeExternal.String(),
},
},
},
},
"external_start_maximal": {
steps: []testStep{
{
config: resourceFreeformSystem{
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
deployMode: apstra.DeployModeDeploy.String(),
systemType: apstra.SystemTypeExternal.String(),
tags: randomStrings(rand.Intn(10)+2, 6),
},
},
{
config: resourceFreeformSystem{
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
systemType: apstra.SystemTypeExternal.String(),
},
},
{
config: resourceFreeformSystem{
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
deployMode: apstra.DeployModeDeploy.String(),
systemType: apstra.SystemTypeExternal.String(),
tags: randomStrings(rand.Intn(10)+2, 6),
},
},
},
},
"internal_start_minimal": {
steps: []testStep{
{
config: resourceFreeformSystem{
Expand All @@ -123,14 +190,13 @@ func TestResourceFreeformSystem(t *testing.T) {
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
deployMode: apstra.DeployModeUndeploy.String(),
systemType: apstra.SystemTypeInternal.String(),
deviceProfileId: string(dpId),
},
},
},
},
"start_with_tags": {
"internal_start_maxmial": {
steps: []testStep{
{
config: resourceFreeformSystem{
Expand All @@ -148,8 +214,7 @@ func TestResourceFreeformSystem(t *testing.T) {
blueprintId: bp.Id().String(),
name: acctest.RandString(6),
hostname: acctest.RandString(6),
deployMode: apstra.DeployModeUndeploy.String(),
systemType: apstra.SystemTypeExternal.String(),
systemType: apstra.SystemTypeInternal.String(),
deviceProfileId: string(dpId),
},
},
Expand All @@ -160,7 +225,7 @@ func TestResourceFreeformSystem(t *testing.T) {
hostname: acctest.RandString(6),
deviceProfileId: string(dpId),
deployMode: apstra.DeployModeDeploy.String(),
systemType: apstra.SystemTypeExternal.String(),
systemType: apstra.SystemTypeInternal.String(),
tags: randomStrings(rand.Intn(10)+2, 6),
},
},
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/freeform_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ output "test_System_out" { value = data.apstra_freeform_system.test }
### Optional

- `deploy_mode` (String) Deploy mode of the System
- `device_profile_id` (String) Device profile ID of the System
- `device_profile_id` (String) Device profile ID of the System. Required when `type` is "internal".
- `system_id` (String) ID (usually serial number) of the Managed Device to associate with this System
- `tags` (Set of String) Set of Tag labels

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ go 1.22.5

require (
github.com/IBM/netaddr v1.5.0
github.com/Juniper/apstra-go-sdk v0.0.0-20240807201924-9a8d4a6b3ebf
github.com/Juniper/apstra-go-sdk v0.0.0-20240813145707-bda42a1f3e8d
github.com/chrismarget-j/go-licenses v0.0.0-20240224210557-f22f3e06d3d4
github.com/google/go-cmp v0.6.0
github.com/hashicorp/go-version v1.7.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/IBM/netaddr v1.5.0 h1:IJlFZe1+nFs09TeMB/HOP4+xBnX2iM/xgiDOgZgTJq0=
github.com/IBM/netaddr v1.5.0/go.mod h1:DDBPeYgbFzoXHjSz9Jwk7K8wmWV4+a/Kv0LqRnb8we4=
github.com/Juniper/apstra-go-sdk v0.0.0-20240807201924-9a8d4a6b3ebf h1:G5MohgVCO8fzW/Z40HTd8xQOyt6mcHXPpIsO/xqQVUA=
github.com/Juniper/apstra-go-sdk v0.0.0-20240807201924-9a8d4a6b3ebf/go.mod h1:cSUzaIIQzZysIVKgJnt2/jO2EKeAB60Xgbx8yBGwJ8Y=
github.com/Juniper/apstra-go-sdk v0.0.0-20240813145707-bda42a1f3e8d h1:CVKhYO0RdUE5zNRoXpKt5Pp1isu52A/u9e1ZarcO6GQ=
github.com/Juniper/apstra-go-sdk v0.0.0-20240813145707-bda42a1f3e8d/go.mod h1:cSUzaIIQzZysIVKgJnt2/jO2EKeAB60Xgbx8yBGwJ8Y=
github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0=
github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
Expand Down

0 comments on commit 22a2428

Please sign in to comment.