diff --git a/docs/resources/virtual_environment_sdn_zone_simple.md b/docs/resources/virtual_environment_sdn_zone_simple.md new file mode 100644 index 00000000..ab922e64 --- /dev/null +++ b/docs/resources/virtual_environment_sdn_zone_simple.md @@ -0,0 +1,30 @@ +--- +layout: page +title: proxmox_virtual_environment_sdn_zone_simple +parent: Resources +subcategory: Virtual Environment +description: |- + Simple Zone in Proxmox SDN. It will create an isolated VNet bridge. This bridge is not linked to a physical interface, and VM traffic is only local on each the node. It can be used in NAT or routed setups. +--- + +# Resource: proxmox_virtual_environment_sdn_zone_simple + +Simple Zone in Proxmox SDN. It will create an isolated VNet bridge. This bridge is not linked to a physical interface, and VM traffic is only local on each the node. It can be used in NAT or routed setups. + + + + +## Schema + +### Required + +- `id` (String) The unique identifier of the SDN zone. + +### Optional + +- `dns` (String) DNS API server address. +- `dns_zone` (String) DNS domain name. Used to register hostnames, such as `.`. The DNS zone must already exist on the DNS server. +- `ipam` (String) IP Address Management system. +- `mtu` (Number) MTU value for the zone. +- `nodes` (Set of String) Proxmox node names. +- `reverse_dns` (String) Reverse DNS API server address. diff --git a/fwprovider/cluster/sdn/zone/resource_model.go b/fwprovider/cluster/sdn/zone/resource_model.go new file mode 100644 index 00000000..4368b7fc --- /dev/null +++ b/fwprovider/cluster/sdn/zone/resource_model.go @@ -0,0 +1,93 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package zone + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + + "github.com/bpg/terraform-provider-proxmox/fwprovider/types/stringset" + "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/sdn/zones" +) + +type baseModel struct { + ID types.String `tfsdk:"id"` + IPAM types.String `tfsdk:"ipam"` + DNS types.String `tfsdk:"dns"` + ReverseDNS types.String `tfsdk:"reverse_dns"` + DNSZone types.String `tfsdk:"dns_zone"` + Nodes stringset.Value `tfsdk:"nodes"` + MTU types.Int64 `tfsdk:"mtu"` + // // VLAN. + // Bridge types.String `tfsdk:"bridge"` + // // QinQ. + // ServiceVLAN types.Int64 `tfsdk:"service_vlan"` + // ServiceVLANProtocol types.String `tfsdk:"service_vlan_protocol"` + // // VXLAN. + // Peers stringset.Value `tfsdk:"peers"` + // // EVPN. + // Controller types.String `tfsdk:"controller"` + // ExitNodes stringset.Value `tfsdk:"exit_nodes"` + // PrimaryExitNode types.String `tfsdk:"primary_exit_node"` + // RouteTargetImport types.String `tfsdk:"rt_import"` + // VRFVXLANID types.Int64 `tfsdk:"vrf_vxlan"` + // ExitNodesLocalRouting types.Bool `tfsdk:"exit_nodes_local_routing"` + // AdvertiseSubnets types.Bool `tfsdk:"advertise_subnets"` + // DisableARPNDSuppression types.Bool `tfsdk:"disable_arp_nd_suppression"` +} + +func (m *baseModel) importFromAPI(name string, data *zones.ZoneData, diags *diag.Diagnostics) { + m.ID = types.StringValue(name) + + m.DNS = types.StringPointerValue(data.DNS) + m.DNSZone = types.StringPointerValue(data.DNSZone) + m.IPAM = types.StringPointerValue(data.IPAM) + m.MTU = types.Int64PointerValue(data.MTU) + m.Nodes = stringset.NewValueString(data.Nodes, diags, stringset.WithSeparator(",")) + m.ReverseDNS = types.StringPointerValue(data.ReverseDNS) + // m.Bridge = types.StringPointerValue(data.Bridge) + // m.ServiceVLAN = types.Int64PointerValue(data.ServiceVLAN) + // m.ServiceVLANProtocol = types.StringPointerValue(data.ServiceVLANProtocol) + // m.Peers = stringset.NewValueString(data.Peers, diags, comaSeparated) + // m.Controller = types.StringPointerValue(data.Controller) + // m.ExitNodes = stringset.NewValueString(data.ExitNodes, diags, comaSeparated) + // m.PrimaryExitNode = types.StringPointerValue(data.ExitNodesPrimary) + // m.RouteTargetImport = types.StringPointerValue(data.RouteTargetImport) + // m.VRFVXLANID = types.Int64PointerValue(data.VRFVXLANID) + // m.ExitNodesLocalRouting = types.BoolPointerValue(ptrConversion.Int64ToBoolPtr(data.ExitNodesLocalRouting)) + // m.AdvertiseSubnets = types.BoolPointerValue(ptrConversion.Int64ToBoolPtr(data.AdvertiseSubnets)) + // m.DisableARPNDSuppression = types.BoolPointerValue(ptrConversion.Int64ToBoolPtr(data.DisableARPNDSuppression)) +} + +func (m *baseModel) toAPIRequestBody(ctx context.Context, diags *diag.Diagnostics) *zones.ZoneRequestData { + data := &zones.ZoneRequestData{} + + data.ID = m.ID.ValueString() + + data.IPAM = m.IPAM.ValueStringPointer() + data.DNS = m.DNS.ValueStringPointer() + data.ReverseDNS = m.ReverseDNS.ValueStringPointer() + data.DNSZone = m.DNSZone.ValueStringPointer() + data.Nodes = m.Nodes.ValueStringPointer(ctx, diags, stringset.WithSeparator(",")) + data.MTU = m.MTU.ValueInt64Pointer() + // data.Bridge = m.Bridge.ValueStringPointer() + // data.ServiceVLAN = m.ServiceVLAN.ValueInt64Pointer() + // data.ServiceVLANProtocol = m.ServiceVLANProtocol.ValueStringPointer() + // data.Peers = m.Peers.ValueStringPointer(ctx, diags, comaSeparated) + // data.Controller = m.Controller.ValueStringPointer() + // data.ExitNodes = m.ExitNodes.ValueStringPointer(ctx, diags, comaSeparated) + // data.ExitNodesPrimary = m.PrimaryExitNode.ValueStringPointer() + // data.RouteTargetImport = m.RouteTargetImport.ValueStringPointer() + // data.VRFVXLANID = m.VRFVXLANID.ValueInt64Pointer() + // data.ExitNodesLocalRouting = ptrConversion.BoolToInt64Ptr(m.ExitNodesLocalRouting.ValueBoolPointer()) + // data.AdvertiseSubnets = ptrConversion.BoolToInt64Ptr(m.AdvertiseSubnets.ValueBoolPointer()) + // data.DisableARPNDSuppression = ptrConversion.BoolToInt64Ptr(m.DisableARPNDSuppression.ValueBoolPointer()) + + return data +} diff --git a/fwprovider/cluster/sdn/zone/resource_schema.go b/fwprovider/cluster/sdn/zone/resource_schema.go new file mode 100644 index 00000000..e26864dd --- /dev/null +++ b/fwprovider/cluster/sdn/zone/resource_schema.go @@ -0,0 +1,213 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package zone + +import ( + "context" + "maps" + "regexp" + + "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "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/schema/validator" + + "github.com/bpg/terraform-provider-proxmox/fwprovider/types/stringset" +) + +func commonAttributes(base ...map[string]schema.Attribute) map[string]schema.Attribute { + if len(base) > 1 { + panic("commonAttributes expects at most one base map") + } + + if len(base) == 0 { + base = append(base, make(map[string]schema.Attribute)) + } + + maps.Copy(base[0], map[string]schema.Attribute{ + "dns": schema.StringAttribute{ + Optional: true, + Description: "DNS API server address.", + }, + "dns_zone": schema.StringAttribute{ + Optional: true, + Description: "DNS domain name. The DNS zone must already exist on the DNS server.", + MarkdownDescription: "DNS domain name. Used to register hostnames, such as `.`. " + + "The DNS zone must already exist on the DNS server.", + }, + "id": schema.StringAttribute{ + Description: "The unique identifier of the SDN zone.", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + // https://github.com/proxmox/pve-network/blob/faaf96a8378a3e41065018562c09c3de0aa434f5/src/PVE/Network/SDN/Zones/Plugin.pm#L34 + stringvalidator.RegexMatches( + regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]*[A-Za-z0-9]$`), + "must be a valid zone identifier", + ), + stringvalidator.LengthAtMost(8), + }, + }, + "ipam": schema.StringAttribute{ + Optional: true, + Description: "IP Address Management system.", + }, + "mtu": schema.Int64Attribute{ + Optional: true, + Description: "MTU value for the zone.", + }, + "nodes": stringset.ResourceAttribute("Proxmox node names.", ""), + "reverse_dns": schema.StringAttribute{ + Optional: true, + Description: "Reverse DNS API server address.", + }, + }) + + return base[0] +} + +func (r *SimpleResource) Schema( + _ context.Context, + _ resource.SchemaRequest, + resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Description: "Simple Zone in Proxmox SDN.", + MarkdownDescription: "Simple Zone in Proxmox SDN. It will create an isolated VNet bridge. " + + "This bridge is not linked to a physical interface, and VM traffic is only local on each the node. " + + "It can be used in NAT or routed setups.", + Attributes: commonAttributes(), + } +} + +func (r *VLAN) Schema( + _ context.Context, + _ resource.SchemaRequest, + resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Description: "VLAN Zone in Proxmox SDN.", + MarkdownDescription: "VLAN Zone in Proxmox SDN. It uses an existing local Linux or OVS bridge to connect to the " + + "node's physical interface. It uses VLAN tagging defined in the VNet to isolate the network segments. " + + "This allows connectivity of VMs between different nodes.", + Attributes: commonAttributes(map[string]schema.Attribute{ + "bridge": schema.StringAttribute{ + Description: "Bridge interface for VLAN.", + MarkdownDescription: "The local bridge or OVS switch, already configured on _each_ node that allows " + + "node-to-node connection.", + Optional: true, + }, + }), + } +} + +func (r *QinQ) Schema( + _ context.Context, + _ resource.SchemaRequest, + resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Description: "QinQ Zone in Proxmox SDN.", + MarkdownDescription: "QinQ Zone in Proxmox SDN. QinQ also known as VLAN stacking, that uses multiple layers of " + + "VLAN tags for isolation. The QinQ zone defines the outer VLAN tag (the Service VLAN) whereas the inner " + + "VLAN tag is defined by the VNet. Your physical network switches must support stacked VLANs for this " + + "configuration. Due to the double stacking of tags, you need 4 more bytes for QinQ VLANs. " + + "For example, you must reduce the MTU to 1496 if you physical interface MTU is 1500.", + Attributes: commonAttributes(map[string]schema.Attribute{ + "bridge": schema.StringAttribute{ + Description: "A local, VLAN-aware bridge that is already configured on each local node", + Optional: true, + }, + "service_vlan": schema.Int64Attribute{ + Optional: true, + Description: "Service VLAN tag for QinQ.", + Validators: []validator.Int64{ + int64validator.Between(int64(1), int64(4094)), + }, + }, + "service_vlan_protocol": schema.StringAttribute{ + Optional: true, + Description: "Service VLAN protocol for QinQ.", + Validators: []validator.String{ + stringvalidator.OneOf("802.1ad", "802.1q"), + }, + }, + }), + } +} + +func (r *VXLAN) Schema( + _ context.Context, + _ resource.SchemaRequest, + resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Description: "VXLAN Zone in Proxmox SDN.", + MarkdownDescription: "VXLAN Zone in Proxmox SDN. It establishes a tunnel (overlay) on top of an existing network " + + "(underlay). This encapsulates layer 2 Ethernet frames within layer 4 UDP datagrams using the default " + + "destination port 4789. You have to configure the underlay network yourself to enable UDP connectivity " + + "between all peers. Because VXLAN encapsulation uses 50 bytes, the MTU needs to be 50 bytes lower than the " + + "outgoing physical interface.", + Attributes: commonAttributes(map[string]schema.Attribute{ + "peers": stringset.ResourceAttribute( + "A list of IP addresses of each node in the VXLAN zone.", + "A list of IP addresses of each node in the VXLAN zone. "+ + "This can be external nodes reachable at this IP address. All nodes in the cluster need to be "+ + "mentioned here", + ), + }), + } +} + +func (r *EVPN) Schema( + _ context.Context, + _ resource.SchemaRequest, + resp *resource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Description: "EVPN Zone in Proxmox SDN.", + MarkdownDescription: "EVPN Zone in Proxmox SDN. The EVPN zone creates a routable Layer 3 network, capable of " + + "spanning across multiple clusters.", + Attributes: commonAttributes(map[string]schema.Attribute{ + "advertise_subnets": schema.BoolAttribute{ + Optional: true, + Description: "Enable subnet advertisement for EVPN.", + }, + "controller": schema.StringAttribute{ + Optional: true, + Description: "EVPN controller address.", + }, + "disable_arp_nd_suppression": schema.BoolAttribute{ + Optional: true, + Description: "Disable ARP/ND suppression for EVPN.", + }, + "exit_nodes": stringset.ResourceAttribute("List of exit nodes for EVPN.", ""), + "exit_nodes_local_routing": schema.BoolAttribute{ + Optional: true, + Description: "Enable local routing for EVPN exit nodes.", + }, + "primary_exit_node": schema.StringAttribute{ + Optional: true, + Description: "Primary exit node for EVPN.", + }, + "rt_import": schema.StringAttribute{ + Optional: true, + Description: "Route target import for EVPN.", + }, + "vrf_vxlan": schema.Int64Attribute{ + Optional: true, + Description: "VRF VXLAN-ID used for dedicated routing interconnect between VNets. It must be different " + + "than the VXLAN-ID of the VNets.", + }, + }), + } +} diff --git a/fwprovider/cluster/sdn/zone/resource_simple.go b/fwprovider/cluster/sdn/zone/resource_simple.go new file mode 100644 index 00000000..a40883d0 --- /dev/null +++ b/fwprovider/cluster/sdn/zone/resource_simple.go @@ -0,0 +1,185 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package zone + +import ( + "context" + "errors" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/resource" + + "github.com/bpg/terraform-provider-proxmox/fwprovider/config" + "github.com/bpg/terraform-provider-proxmox/proxmox/api" + "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/sdn/zones" + "github.com/bpg/terraform-provider-proxmox/proxmox/helpers/ptr" +) + +var ( + _ resource.ResourceWithConfigure = &SimpleResource{} + _ resource.ResourceWithImportState = &SimpleResource{} +) + +type SimpleResource struct { + client *zones.Client +} + +// NewSimpleResource creates a new instance of the Simple resource. +func NewSimpleResource() resource.Resource { + return &SimpleResource{} +} + +// Metadata defines the name of the resource. +func (r *SimpleResource) Metadata( + _ context.Context, + req resource.MetadataRequest, + resp *resource.MetadataResponse, +) { + resp.TypeName = req.ProviderTypeName + "_sdn_zone_simple" +} + +func (r *SimpleResource) Configure( + _ context.Context, + req resource.ConfigureRequest, + resp *resource.ConfigureResponse, +) { + if req.ProviderData == nil { + return + } + + cfg, ok := req.ProviderData.(config.Resource) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf( + "Expected config.Resource, got: %T", + req.ProviderData, + ), + ) + + return + } + + r.client = cfg.Client.Cluster().SDNZones() +} + +func (r *SimpleResource) Create( + ctx context.Context, + req resource.CreateRequest, + resp *resource.CreateResponse, +) { + var plan baseModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + + if resp.Diagnostics.HasError() { + return + } + + reqData := plan.toAPIRequestBody(ctx, &resp.Diagnostics) + reqData.Type = ptr.Ptr(zones.TypeSimple) + + if err := r.client.CreateZone(ctx, reqData); err != nil { + resp.Diagnostics.AddError( + "Unable to Create SDN Zone", + err.Error(), + ) + + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *SimpleResource) Read( + ctx context.Context, + req resource.ReadRequest, + resp *resource.ReadResponse, +) { + var state baseModel + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + zone, err := r.client.GetZone(ctx, state.ID.ValueString()) + if err != nil { + if errors.Is(err, api.ErrResourceDoesNotExist) { + resp.State.RemoveResource(ctx) + return + } + + resp.Diagnostics.AddError( + "Unable to Read SDN Zone", + err.Error(), + ) + + return + } + + readModel := &baseModel{} + readModel.importFromAPI(zone.ID, zone, &resp.Diagnostics) + resp.Diagnostics.Append(resp.State.Set(ctx, readModel)...) +} + +func (r *SimpleResource) Update( + ctx context.Context, + req resource.UpdateRequest, + resp *resource.UpdateResponse, +) { + var plan baseModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + + if resp.Diagnostics.HasError() { + return + } + + reqData := plan.toAPIRequestBody(ctx, &resp.Diagnostics) + + if err := r.client.UpdateZone(ctx, reqData); err != nil { + resp.Diagnostics.AddError( + "Unable to Update SDN Zone", + err.Error(), + ) + + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *SimpleResource) Delete( + ctx context.Context, + req resource.DeleteRequest, + resp *resource.DeleteResponse, +) { + var state baseModel + + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + if err := r.client.DeleteZone(ctx, state.ID.ValueString()); err != nil && + !errors.Is(err, api.ErrResourceDoesNotExist) { + resp.Diagnostics.AddError( + "Unable to Delete SDN Zone", + err.Error(), + ) + } +} + +func (r *SimpleResource) ImportState( + ctx context.Context, + req resource.ImportStateRequest, + resp *resource.ImportStateResponse, +) { +} diff --git a/fwprovider/cluster/sdn/zone/resource_simple_test.go b/fwprovider/cluster/sdn/zone/resource_simple_test.go new file mode 100644 index 00000000..8ce5c307 --- /dev/null +++ b/fwprovider/cluster/sdn/zone/resource_simple_test.go @@ -0,0 +1,53 @@ +//go:build acceptance || all + +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package zone_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/bpg/terraform-provider-proxmox/fwprovider/test" +) + +func TestAccResourceSDNZoneSimple(t *testing.T) { + te := test.InitEnvironment(t) + + tests := []struct { + name string + steps []resource.TestStep + }{ + {"create and update zones", []resource.TestStep{{ + Config: te.RenderConfig(` + resource "proxmox_virtual_environment_sdn_zone_simple" "zone_simple" { + id = "zoneS" + nodes = ["pve"] + mtu = 1496 + } + `), + }, { + Config: te.RenderConfig(` + resource "proxmox_virtual_environment_sdn_zone_simple" "zone_simple" { + id = "zoneS" + nodes = ["pve"] + mtu = 1495 + } + `), + }}}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: te.AccProviders, + Steps: tt.steps, + }) + }) + } +} diff --git a/fwprovider/provider.go b/fwprovider/provider.go index c578e2e8..b657c5cc 100644 --- a/fwprovider/provider.go +++ b/fwprovider/provider.go @@ -30,6 +30,7 @@ import ( "github.com/bpg/terraform-provider-proxmox/fwprovider/cluster/hardwaremapping" "github.com/bpg/terraform-provider-proxmox/fwprovider/cluster/metrics" "github.com/bpg/terraform-provider-proxmox/fwprovider/cluster/options" + sdnzone "github.com/bpg/terraform-provider-proxmox/fwprovider/cluster/sdn/zone" "github.com/bpg/terraform-provider-proxmox/fwprovider/config" "github.com/bpg/terraform-provider-proxmox/fwprovider/nodes" "github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/apt" @@ -527,6 +528,11 @@ func (p *proxmoxProvider) Resources(_ context.Context) []func() resource.Resourc nodes.NewDownloadFileResource, options.NewClusterOptionsResource, vm.NewResource, + sdnzone.NewSimpleResource, + // + // sdn.NewSDNZoneResource, + // sdn.NewSDNVnetResource, + //sdn.NewSDNSubnetResource, } } @@ -550,6 +556,9 @@ func (p *proxmoxProvider) DataSources(_ context.Context) []func() datasource.Dat hardwaremapping.NewUSBDataSource, metrics.NewMetricsServerDatasource, vm.NewDataSource, + // sdn.NewSDNZoneDataSource, + // sdn.NewSDNVnetDataSource, + // sdn.NewSDNSubnetDataSource, } } diff --git a/main.go b/main.go index 0395120e..c71c3b4e 100644 --- a/main.go +++ b/main.go @@ -65,6 +65,7 @@ import ( //go:generate cp ./build/docs-gen/resources/virtual_environment_haresource.md ./docs/resources/ //go:generate cp ./build/docs-gen/resources/virtual_environment_network_linux_bridge.md ./docs/resources/ //go:generate cp ./build/docs-gen/resources/virtual_environment_network_linux_vlan.md ./docs/resources/ +//go:generate cp ./build/docs-gen/resources/virtual_environment_sdn_zone_simple.md ./docs/resources/ //go:generate cp ./build/docs-gen/resources/virtual_environment_user_token.md ./docs/resources/ //go:generate cp ./build/docs-gen/resources/virtual_environment_vm2.md ./docs/resources/ //go:generate cp ./build/docs-gen/resources/virtual_environment_metrics_server.md ./docs/resources/ diff --git a/proxmox/cluster/client.go b/proxmox/cluster/client.go index e4f2314a..f0accdf1 100644 --- a/proxmox/cluster/client.go +++ b/proxmox/cluster/client.go @@ -15,6 +15,7 @@ import ( "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/ha" "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/mapping" "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/metrics" + "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/sdn/zones" "github.com/bpg/terraform-provider-proxmox/proxmox/firewall" ) @@ -54,3 +55,18 @@ func (c *Client) ACME() *acme.Client { func (c *Client) Metrics() *metrics.Client { return &metrics.Client{Client: c} } + +// SDNZones returns a client for managing the cluster's SDN zones. +func (c *Client) SDNZones() *zones.Client { + return &zones.Client{Client: c} +} + +// // SDNVnets returns a client for managing the cluster's SDN Vnets. +// func (c *Client) SDNVnets() *vnets.Client { +// return &vnets.Client{Client: c} +// } + +// // SDNSubnets returns a client for managing the cluster's SDN Subnets. +// func (c *Client) SDNSubnets() *subnets.Client { +// return &subnets.Client{Client: c} +// } diff --git a/proxmox/cluster/sdn/zones/zones_types.go b/proxmox/cluster/sdn/zones/zones_types.go index f463cd26..d753bc15 100644 --- a/proxmox/cluster/sdn/zones/zones_types.go +++ b/proxmox/cluster/sdn/zones/zones_types.go @@ -6,8 +6,16 @@ package zones +const ( + TypeSimple = "simple" + TypeVLAN = "vlan" + TypeQinQ = "qinq" + TypeVXLAN = "vxlan" + TypeEVPN = "evpn" +) + type ZoneData struct { - ID string `json:"zone,omitempty" url:"zone,omitempty"` + ID string `json:"zone" url:"zone"` Type *string `json:"type,omitempty" url:"type,omitempty"` IPAM *string `json:"ipam,omitempty" url:"ipam,omitempty"` DNS *string `json:"dns,omitempty" url:"dns,omitempty"` @@ -40,6 +48,7 @@ type ZoneData struct { // ZoneRequestData wraps a ZoneData struct with optional delete instructions. type ZoneRequestData struct { ZoneData + Delete []string `url:"delete,omitempty"` } diff --git a/testacc b/testacc index b022b53b..0959e631 100755 --- a/testacc +++ b/testacc @@ -6,5 +6,21 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. # -# shellcheck disable=SC2046 -TF_ACC=1 env $(xargs < testacc.env) go test -count 1 --tags=acceptance -timeout 360s -run "$1" github.com/bpg/terraform-provider-proxmox/fwprovider/... $2 +BASE_PKG="github.com/bpg/terraform-provider-proxmox" + +find_test_package() { + test_name="$1" + [ -z "$test_name" ] && echo "${BASE_PKG}/fwprovider/..." && return + + test_file=$(find . -name "*.go" -type f -exec grep -l "func ${test_name}(" {} \; | head -1) + [ -z "$test_file" ] && echo "${BASE_PKG}/fwprovider/..." && return + + package_dir=$(dirname "$test_file") + package_path=$(echo "$package_dir" | sed 's|^\./||') + echo "${BASE_PKG}/${package_path}" +} + +PACKAGE_PATH=$(find_test_package "$1") + +# shellcheck disable=SC2046,SC2086 +TF_ACC=1 env $(xargs < testacc.env) go test -count 1 --tags=acceptance -timeout 360s -run "$1" "$PACKAGE_PATH" $2