-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #760 from Juniper/754-freeform-allocation-groups
754 freeform allocation groups
- Loading branch information
Showing
17 changed files
with
1,076 additions
and
6 deletions.
There are no files selected for viewing
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,134 @@ | ||
package blueprint | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
|
||
"github.com/Juniper/apstra-go-sdk/apstra" | ||
"github.com/Juniper/terraform-provider-apstra/apstra/utils" | ||
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" | ||
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" | ||
dataSourceSchema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/diag" | ||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
resourceSchema "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/schema/validator" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
type FreeformAllocGroup struct { | ||
BlueprintId types.String `tfsdk:"blueprint_id"` | ||
Id types.String `tfsdk:"id"` | ||
Name types.String `tfsdk:"name"` | ||
Type types.String `tfsdk:"type"` | ||
PoolIds types.Set `tfsdk:"pool_ids"` | ||
} | ||
|
||
func (o FreeformAllocGroup) DataSourceAttributes() map[string]dataSourceSchema.Attribute { | ||
return map[string]dataSourceSchema.Attribute{ | ||
"blueprint_id": dataSourceSchema.StringAttribute{ | ||
MarkdownDescription: "Apstra Blueprint ID. Used to identify " + | ||
"the Blueprint where the Allocation Group lives.", | ||
Required: true, | ||
Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, | ||
}, | ||
"id": dataSourceSchema.StringAttribute{ | ||
MarkdownDescription: "Populate this field to look up the Allocation Group by ID. Required when `name` is omitted.", | ||
Optional: true, | ||
Computed: true, | ||
Validators: []validator.String{ | ||
stringvalidator.LengthAtLeast(1), | ||
stringvalidator.ExactlyOneOf(path.Expressions{ | ||
path.MatchRelative(), | ||
path.MatchRoot("name"), | ||
}...), | ||
}, | ||
}, | ||
"name": dataSourceSchema.StringAttribute{ | ||
MarkdownDescription: "Populate this field to look up the Allocation Group by Name. Required when `id` is omitted.", | ||
Optional: true, | ||
Computed: true, | ||
Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, | ||
}, | ||
"type": dataSourceSchema.StringAttribute{ | ||
MarkdownDescription: fmt.Sprintf("type of the Allocation Group, must be one of :\n - `" + | ||
strings.Join(utils.AllResourcePoolTypes(), "`\n - `") + "`\n"), | ||
Computed: true, | ||
}, | ||
"pool_ids": dataSourceSchema.SetAttribute{ | ||
MarkdownDescription: "IDs of Resource Pools assigned to the allocation group", | ||
Computed: true, | ||
ElementType: types.StringType, | ||
}, | ||
} | ||
} | ||
|
||
func (o FreeformAllocGroup) ResourceAttributes() map[string]resourceSchema.Attribute { | ||
return map[string]resourceSchema.Attribute{ | ||
"blueprint_id": resourceSchema.StringAttribute{ | ||
MarkdownDescription: "Apstra Blueprint ID.", | ||
Required: true, | ||
Validators: []validator.String{stringvalidator.LengthAtLeast(1)}, | ||
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()}, | ||
}, | ||
"id": resourceSchema.StringAttribute{ | ||
MarkdownDescription: "ID of the Freeform Allocation Group.", | ||
Computed: true, | ||
PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, | ||
}, | ||
"name": resourceSchema.StringAttribute{ | ||
MarkdownDescription: "Freeform Allocation Group name as shown in the Web UI.", | ||
Required: true, | ||
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()}, | ||
Validators: []validator.String{ | ||
stringvalidator.RegexMatches(regexp.MustCompile("^[a-zA-Z0-9.-_]+$"), | ||
"name may consist only of the following characters : a-zA-Z0-9.-_"), | ||
}, | ||
}, | ||
"type": resourceSchema.StringAttribute{ | ||
MarkdownDescription: fmt.Sprintf("type of the Allocation Group, must be one of :\n - `" + | ||
strings.Join(utils.AllResourcePoolTypes(), "`\n - `") + "`\n"), | ||
Required: true, | ||
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()}, | ||
Validators: []validator.String{stringvalidator.OneOf(utils.AllFFResourceTypes()...)}, | ||
}, | ||
"pool_ids": resourceSchema.SetAttribute{ | ||
MarkdownDescription: "IDs of Resource Pools assigned to the allocation group", | ||
ElementType: types.StringType, | ||
Required: true, | ||
Validators: []validator.Set{setvalidator.SizeAtLeast(1)}, | ||
}, | ||
} | ||
} | ||
|
||
func (o *FreeformAllocGroup) Request(ctx context.Context, diags *diag.Diagnostics) *apstra.FreeformAllocGroupData { | ||
// unpack | ||
var allocGroupType apstra.ResourcePoolType | ||
err := utils.ApiStringerFromFriendlyString(&allocGroupType, o.Type.ValueString()) | ||
if err != nil { | ||
diags.AddError(fmt.Sprintf("error parsing type %q", o.Type.ValueString()), err.Error()) | ||
} | ||
|
||
var poolIds []apstra.ObjectId | ||
diags.Append(o.PoolIds.ElementsAs(ctx, &poolIds, false)...) | ||
if diags.HasError() { | ||
return nil | ||
} | ||
|
||
return &apstra.FreeformAllocGroupData{ | ||
Name: o.Name.ValueString(), | ||
Type: allocGroupType, | ||
PoolIds: poolIds, | ||
} | ||
} | ||
|
||
func (o *FreeformAllocGroup) LoadApiData(ctx context.Context, in *apstra.FreeformAllocGroupData, diags *diag.Diagnostics) { | ||
// pack | ||
o.Name = types.StringValue(in.Name) | ||
o.Type = types.StringValue(utils.StringersToFriendlyString(in.Type)) | ||
o.PoolIds = utils.SetValueOrNull(ctx, types.StringType, in.PoolIds, diags) | ||
} |
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,101 @@ | ||
package tfapstra | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/Juniper/apstra-go-sdk/apstra" | ||
"github.com/Juniper/terraform-provider-apstra/apstra/blueprint" | ||
"github.com/Juniper/terraform-provider-apstra/apstra/utils" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource" | ||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
var ( | ||
_ datasource.DataSourceWithConfigure = &dataSourceFreeformAllocGroup{} | ||
_ datasourceWithSetFfBpClientFunc = &dataSourceFreeformAllocGroup{} | ||
) | ||
|
||
type dataSourceFreeformAllocGroup struct { | ||
getBpClientFunc func(context.Context, string) (*apstra.FreeformClient, error) | ||
} | ||
|
||
func (o *dataSourceFreeformAllocGroup) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { | ||
resp.TypeName = req.ProviderTypeName + "_freeform_alloc_group" | ||
} | ||
|
||
func (o *dataSourceFreeformAllocGroup) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { | ||
configureDataSource(ctx, o, req, resp) | ||
} | ||
|
||
func (o *dataSourceFreeformAllocGroup) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
MarkdownDescription: docCategoryFreeform + "This data source provides details of a Freeform Allocation Group.\n\n" + | ||
"At least one optional attribute is required.", | ||
Attributes: blueprint.FreeformAllocGroup{}.DataSourceAttributes(), | ||
} | ||
} | ||
|
||
func (o *dataSourceFreeformAllocGroup) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { | ||
var config blueprint.FreeformAllocGroup | ||
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
// get a client for the Freeform reference design | ||
bp, err := o.getBpClientFunc(ctx, config.BlueprintId.ValueString()) | ||
if err != nil { | ||
if utils.IsApstra404(err) { | ||
resp.Diagnostics.AddError(fmt.Sprintf("blueprint %s not found", config.BlueprintId), err.Error()) | ||
return | ||
} | ||
resp.Diagnostics.AddError("failed to create blueprint client", err.Error()) | ||
return | ||
} | ||
|
||
var api *apstra.FreeformAllocGroup | ||
switch { | ||
case !config.Id.IsNull(): | ||
api, err = bp.GetAllocGroup(ctx, apstra.ObjectId(config.Id.ValueString())) | ||
if utils.IsApstra404(err) { | ||
resp.Diagnostics.AddAttributeError( | ||
path.Root("id"), | ||
"Freeform Allocation Group not found", | ||
fmt.Sprintf("Freeform Allocation Group with ID %s not found", config.Id)) | ||
return | ||
} | ||
case !config.Name.IsNull(): | ||
api, err = bp.GetAllocGroupByName(ctx, config.Name.ValueString()) | ||
if utils.IsApstra404(err) { | ||
resp.Diagnostics.AddAttributeError( | ||
path.Root("name"), | ||
"Freeform Allocation Group not found", | ||
fmt.Sprintf("Freeform Allocation Group with Name %s not found", config.Name)) | ||
return | ||
} | ||
} | ||
if err != nil { | ||
resp.Diagnostics.AddError("failed reading Freeform Allocation Group", err.Error()) | ||
return | ||
} | ||
if api.Data == nil { | ||
resp.Diagnostics.AddError("failed reading Freeform Allocation Group", "api response has no payload") | ||
return | ||
} | ||
|
||
config.Id = types.StringValue(api.Id.String()) | ||
config.LoadApiData(ctx, api.Data, &resp.Diagnostics) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
// Set state | ||
resp.Diagnostics.Append(resp.State.Set(ctx, &config)...) | ||
} | ||
|
||
func (o *dataSourceFreeformAllocGroup) setBpClientFunc(f func(context.Context, string) (*apstra.FreeformClient, error)) { | ||
o.getBpClientFunc = f | ||
} |
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
Oops, something went wrong.