From d2b212cf511ddbb918337d3e177aa9186c2c2ab8 Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Mon, 29 Jul 2024 14:48:40 +0200 Subject: [PATCH 01/20] Fixed id referencing in datasources --- cloudconnexa/data_source_application.go | 4 ++++ cloudconnexa/data_source_connector.go | 9 +++++---- cloudconnexa/data_source_host.go | 8 ++------ cloudconnexa/data_source_network.go | 8 ++------ cloudconnexa/data_source_network_routes.go | 7 ++----- cloudconnexa/data_source_user.go | 8 ++------ cloudconnexa/data_source_user_group.go | 8 ++------ cloudconnexa/data_source_vpn_region.go | 8 ++------ example/applications.tf | 6 +++--- example/connectors.tf | 2 +- example/services.tf | 2 +- 11 files changed, 26 insertions(+), 44 deletions(-) diff --git a/cloudconnexa/data_source_application.go b/cloudconnexa/data_source_application.go index 3614589..691cc97 100644 --- a/cloudconnexa/data_source_application.go +++ b/cloudconnexa/data_source_application.go @@ -11,6 +11,10 @@ func dataSourceApplication() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceApplicationRead, Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, "name": { Type: schema.TypeString, Required: true, diff --git a/cloudconnexa/data_source_connector.go b/cloudconnexa/data_source_connector.go index c7f9307..717faaa 100644 --- a/cloudconnexa/data_source_connector.go +++ b/cloudconnexa/data_source_connector.go @@ -2,9 +2,6 @@ package cloudconnexa import ( "context" - "strconv" - "time" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" @@ -15,6 +12,10 @@ func dataSourceConnector() *schema.Resource { Description: "Use an `cloudconnexa_connector` data source to read an existing CloudConnexa connector.", ReadContext: dataSourceConnectorRead, Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, "name": { Type: schema.TypeString, Required: true, @@ -66,6 +67,7 @@ func dataSourceConnectorRead(ctx context.Context, d *schema.ResourceData, m inte if err != nil { return append(diags, diag.FromErr(err)...) } + d.SetId(connector.Id) d.Set("name", connector.Name) d.Set("description", connector.Description) d.Set("network_item_id", connector.NetworkItemId) @@ -78,6 +80,5 @@ func dataSourceConnectorRead(ctx context.Context, d *schema.ResourceData, m inte return append(diags, diag.FromErr(err)...) } d.Set("profile", profile) - d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) return diags } diff --git a/cloudconnexa/data_source_host.go b/cloudconnexa/data_source_host.go index f095c89..caaea8a 100644 --- a/cloudconnexa/data_source_host.go +++ b/cloudconnexa/data_source_host.go @@ -2,9 +2,6 @@ package cloudconnexa import ( "context" - "strconv" - "time" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" @@ -15,7 +12,7 @@ func dataSourceHost() *schema.Resource { Description: "Use an `cloudconnexa_host` data source to read an existing CloudConnexa connector.", ReadContext: dataSourceHostRead, Schema: map[string]*schema.Schema{ - "host_id": { + "id": { Type: schema.TypeString, Computed: true, Description: "The host ID.", @@ -93,12 +90,11 @@ func dataSourceHostRead(ctx context.Context, d *schema.ResourceData, m interface if err != nil { return append(diags, diag.FromErr(err)...) } - d.Set("host_id", host.Id) + d.SetId(host.Id) d.Set("name", host.Name) d.Set("internet_access", host.InternetAccess) d.Set("system_subnets", host.SystemSubnets) d.Set("connectors", getConnectorsSliceByConnectors(&host.Connectors)) - d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) return diags } diff --git a/cloudconnexa/data_source_network.go b/cloudconnexa/data_source_network.go index 1a68382..d833e26 100644 --- a/cloudconnexa/data_source_network.go +++ b/cloudconnexa/data_source_network.go @@ -2,9 +2,6 @@ package cloudconnexa import ( "context" - "strconv" - "time" - "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -16,7 +13,7 @@ func dataSourceNetwork() *schema.Resource { Description: "Use a `cloudconnexa_network` data source to read an CloudConnexa network.", ReadContext: dataSourceNetworkRead, Schema: map[string]*schema.Schema{ - "network_id": { + "id": { Type: schema.TypeString, Computed: true, Description: "The network ID.", @@ -132,7 +129,7 @@ func dataSourceNetworkRead(ctx context.Context, d *schema.ResourceData, m interf if network == nil { return append(diags, diag.Errorf("Network with name %s was not found", networkName)...) } - d.Set("network_id", network.Id) + d.SetId(network.Id) d.Set("name", network.Name) d.Set("description", network.Description) d.Set("egress", network.Egress) @@ -140,7 +137,6 @@ func dataSourceNetworkRead(ctx context.Context, d *schema.ResourceData, m interf d.Set("system_subnets", network.SystemSubnets) d.Set("routes", getRoutesSlice(&network.Routes)) d.Set("connectors", getConnectorsSliceByNetworkConnectors(&network.Connectors)) - d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) return diags } diff --git a/cloudconnexa/data_source_network_routes.go b/cloudconnexa/data_source_network_routes.go index 557c57a..727d1d2 100644 --- a/cloudconnexa/data_source_network_routes.go +++ b/cloudconnexa/data_source_network_routes.go @@ -2,9 +2,6 @@ package cloudconnexa import ( "context" - "strconv" - "time" - "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -16,7 +13,7 @@ func dataSourceNetworkRoutes() *schema.Resource { Description: "Use an `cloudconnexa_network_routes` data source to read all the routes associated with an CloudConnexa network.", ReadContext: dataSourceNetworkRoutesRead, Schema: map[string]*schema.Schema{ - "network_item_id": { + "id": { Type: schema.TypeString, Required: true, Description: "The id of the CloudConnexa network of the routes to be discovered.", @@ -77,7 +74,7 @@ func dataSourceNetworkRoutesRead(ctx context.Context, d *schema.ResourceData, m if err := d.Set("routes", configRoutes); err != nil { return append(diags, diag.FromErr(err)...) } + d.SetId(networkId) - d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) return diags } diff --git a/cloudconnexa/data_source_user.go b/cloudconnexa/data_source_user.go index d327f44..c5f1a97 100644 --- a/cloudconnexa/data_source_user.go +++ b/cloudconnexa/data_source_user.go @@ -2,9 +2,6 @@ package cloudconnexa import ( "context" - "strconv" - "time" - "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -16,7 +13,7 @@ func dataSourceUser() *schema.Resource { Description: "Use a `cloudconnexa_user` data source to read a specific CloudConnexa user.", ReadContext: dataSourceUserRead, Schema: map[string]*schema.Schema{ - "user_id": { + "id": { Type: schema.TypeString, Computed: true, Description: "The ID of this resource.", @@ -111,7 +108,7 @@ func dataSourceUserRead(ctx context.Context, d *schema.ResourceData, m interface return append(diags, diag.Errorf("User with name %s was not found", userName)...) } - d.Set("user_id", user.Id) + d.SetId(user.Id) d.Set("username", user.Username) d.Set("role", user.Role) d.Set("email", user.Email) @@ -121,7 +118,6 @@ func dataSourceUserRead(ctx context.Context, d *schema.ResourceData, m interface d.Set("group_id", user.GroupId) d.Set("status", user.Status) d.Set("devices", getUserDevicesSlice(&user.Devices)) - d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) return diags } diff --git a/cloudconnexa/data_source_user_group.go b/cloudconnexa/data_source_user_group.go index 43a0763..35b6fb1 100644 --- a/cloudconnexa/data_source_user_group.go +++ b/cloudconnexa/data_source_user_group.go @@ -2,9 +2,6 @@ package cloudconnexa import ( "context" - "strconv" - "time" - "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -16,7 +13,7 @@ func dataSourceUserGroup() *schema.Resource { Description: "Use an `cloudconnexa_user_group` data source to read an CloudConnexa user group.", ReadContext: dataSourceUserGroupRead, Schema: map[string]*schema.Schema{ - "user_group_id": { + "id": { Type: schema.TypeString, Computed: true, Description: "The user group ID.", @@ -67,12 +64,11 @@ func dataSourceUserGroupRead(ctx context.Context, d *schema.ResourceData, m inte if userGroup == nil { return append(diags, diag.Errorf("User group with name %s was not found", userGroupName)...) } - d.Set("user_group_id", userGroup.ID) + d.SetId(userGroup.ID) d.Set("name", userGroup.Name) d.Set("vpn_region_ids", userGroup.VpnRegionIds) d.Set("internet_access", userGroup.InternetAccess) d.Set("max_device", userGroup.MaxDevice) d.Set("system_subnets", userGroup.SystemSubnets) - d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) return diags } diff --git a/cloudconnexa/data_source_vpn_region.go b/cloudconnexa/data_source_vpn_region.go index 3bab8f0..550a265 100644 --- a/cloudconnexa/data_source_vpn_region.go +++ b/cloudconnexa/data_source_vpn_region.go @@ -2,9 +2,6 @@ package cloudconnexa import ( "context" - "strconv" - "time" - "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -16,7 +13,7 @@ func dataSourceVpnRegion() *schema.Resource { Description: "Use a `cloudconnexa_vpn_region` data source to read an CloudConnexa VPN region.", ReadContext: dataSourceVpnRegionRead, Schema: map[string]*schema.Schema{ - "region_id": { + "id": { Type: schema.TypeString, Required: true, Description: "The id of the region.", @@ -56,11 +53,10 @@ func dataSourceVpnRegionRead(ctx context.Context, d *schema.ResourceData, m inte if vpnRegion == nil { return append(diags, diag.Errorf("VPN region with id %s was not found", vpnRegionId)...) } - d.Set("region_id", vpnRegion.Id) + d.SetId(vpnRegion.Id) d.Set("continent", vpnRegion.Continent) d.Set("country", vpnRegion.Country) d.Set("country_iso", vpnRegion.CountryISO) d.Set("region_name", vpnRegion.RegionName) - d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) return diags } diff --git a/example/applications.tf b/example/applications.tf index ea4bf03..d314a78 100644 --- a/example/applications.tf +++ b/example/applications.tf @@ -5,7 +5,7 @@ data "cloudconnexa_network" "test-net" { resource "cloudconnexa_application" "application_full_access" { name = "example-application-1" network_item_type = "NETWORK" - network_item_id = data.cloudconnexa_network.test-net.network_id + network_item_id = data.cloudconnexa_network.test-net.id routes { domain = "example-application-1.com" allow_embedded_ip = false @@ -19,7 +19,7 @@ resource "cloudconnexa_application" "application_full_access" { resource "cloudconnexa_application" "application_custom_access" { name = "example-application-2" network_item_type = "NETWORK" - network_item_id = data.cloudconnexa_network.test-net.network_id + network_item_id = data.cloudconnexa_network.test-net.id routes { domain = "example-application-2.com" @@ -72,7 +72,7 @@ resource "cloudconnexa_application" "application_custom_access_advanced" { name = each.key description = try(each.value.description, local.created_by) network_item_type = "NETWORK" - network_item_id = data.cloudconnexa_network.test-net.network_id + network_item_id = data.cloudconnexa_network.test-net.id config { service_types = ["ANY"] } diff --git a/example/connectors.tf b/example/connectors.tf index a345ff9..eda31da 100644 --- a/example/connectors.tf +++ b/example/connectors.tf @@ -6,5 +6,5 @@ resource "cloudconnexa_connector" "test-connector" { name = "test-connector" vpn_region_id = "eu-central-1" network_item_type = "NETWORK" - network_item_id = data.cloudconnexa_network.test-net.network_id + network_item_id = data.cloudconnexa_network.test-net.id } diff --git a/example/services.tf b/example/services.tf index 764eb22..30d6d21 100644 --- a/example/services.tf +++ b/example/services.tf @@ -8,7 +8,7 @@ resource "cloudconnexa_ip_service" "test-service" { description = "test-description" routes = ["10.0.0.2/32"] network_item_type = "NETWORK" - network_item_id = data.cloudconnexa_network.test-net.network_id + network_item_id = data.cloudconnexa_network.test-net.id config { service_types = ["ANY"] From d4ecc51800921dc8c5814dba35c6d2e5e31195d2 Mon Sep 17 00:00:00 2001 From: vladhanzha Date: Mon, 29 Jul 2024 18:36:15 +0300 Subject: [PATCH 02/20] Add missing host fields --- cloudconnexa/data_source_host.go | 17 +++++++++++++++++ cloudconnexa/resource_host.go | 23 ++++++++++++++++++++++- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/cloudconnexa/data_source_host.go b/cloudconnexa/data_source_host.go index f095c89..33efb41 100644 --- a/cloudconnexa/data_source_host.go +++ b/cloudconnexa/data_source_host.go @@ -25,6 +25,16 @@ func dataSourceHost() *schema.Resource { Required: true, Description: "The name of the host.", }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the host.", + }, + "domain": { + Type: schema.TypeString, + Computed: true, + Description: "The host domain.", + }, "internet_access": { Type: schema.TypeString, Computed: true, @@ -54,6 +64,11 @@ func dataSourceHost() *schema.Resource { Computed: true, Description: "The connector name.", }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The connector description.", + }, "network_item_id": { Type: schema.TypeString, Computed: true, @@ -95,6 +110,8 @@ func dataSourceHostRead(ctx context.Context, d *schema.ResourceData, m interface } d.Set("host_id", host.Id) d.Set("name", host.Name) + d.Set("description", host.Description) + d.Set("domain", host.Domain) d.Set("internet_access", host.InternetAccess) d.Set("system_subnets", host.SystemSubnets) d.Set("connectors", getConnectorsSliceByConnectors(&host.Connectors)) diff --git a/cloudconnexa/resource_host.go b/cloudconnexa/resource_host.go index 37657a1..424f494 100644 --- a/cloudconnexa/resource_host.go +++ b/cloudconnexa/resource_host.go @@ -34,6 +34,12 @@ func resourceHost() *schema.Resource { ValidateFunc: validation.StringLenBetween(1, 120), Description: "The description for the UI. Defaults to `Managed by Terraform`.", }, + "domain": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 253), + Description: "The domain of the host.", + }, "internet_access": { Type: schema.TypeString, Optional: true, @@ -70,6 +76,13 @@ func resourceHost() *schema.Resource { Required: true, Description: "Name of the connector associated with this host.", }, + "description": { + Type: schema.TypeString, + Optional: true, + Default: "Managed by Terraform", + ValidateFunc: validation.StringLenBetween(1, 120), + Description: "The description for the UI. Defaults to `Managed by Terraform`.", + }, "vpn_region_id": { Type: schema.TypeString, Required: true, @@ -114,11 +127,13 @@ func resourceHostCreate(ctx context.Context, d *schema.ResourceData, m interface for _, c := range configConnectors.List() { connectors = append(connectors, cloudconnexa.Connector{ Name: c.(map[string]interface{})["name"].(string), + Description: c.(map[string]interface{})["description"].(string), VpnRegionId: c.(map[string]interface{})["vpn_region_id"].(string), }) } h := cloudconnexa.Host{ Name: d.Get("name").(string), + Domain: d.Get("domain").(string), Description: d.Get("description").(string), InternetAccess: d.Get("internet_access").(string), Connectors: connectors, @@ -153,6 +168,7 @@ func resourceHostRead(ctx context.Context, d *schema.ResourceData, m interface{} } d.Set("name", host.Name) d.Set("description", host.Description) + d.Set("domain", host.Domain) d.Set("internet_access", host.InternetAccess) d.Set("system_subnets", host.SystemSubnets) @@ -174,6 +190,7 @@ func resourceHostUpdate(ctx context.Context, d *schema.ResourceData, m interface // This happens when importing the resource newConnector := cloudconnexa.Connector{ Name: newSet.List()[0].(map[string]interface{})["name"].(string), + Description: newSet.List()[0].(map[string]interface{})["description"].(string), VpnRegionId: newSet.List()[0].(map[string]interface{})["vpn_region_id"].(string), NetworkItemType: "HOST", } @@ -194,6 +211,7 @@ func resourceHostUpdate(ctx context.Context, d *schema.ResourceData, m interface if !oldSet.Contains(n) { newConnector := cloudconnexa.Connector{ Name: n.(map[string]interface{})["name"].(string), + Description: n.(map[string]interface{})["description"].(string), VpnRegionId: n.(map[string]interface{})["vpn_region_id"].(string), NetworkItemType: "HOST", } @@ -205,14 +223,16 @@ func resourceHostUpdate(ctx context.Context, d *schema.ResourceData, m interface } } } - if d.HasChanges("name", "description", "internet_access") { + if d.HasChanges("name", "description", "domain", "internet_access") { _, newName := d.GetChange("name") _, newDescription := d.GetChange("description") + _, newDomain := d.GetChange("domain") _, newAccess := d.GetChange("internet_access") err := c.Hosts.Update(cloudconnexa.Host{ Id: d.Id(), Name: newName.(string), Description: newDescription.(string), + Domain: newDomain.(string), InternetAccess: newAccess.(string), }) if err != nil { @@ -253,6 +273,7 @@ func getConnectorsListItem(c *cloudconnexa.Client, connector cloudconnexa.Connec connectorsData := map[string]interface{}{ "id": connector.Id, "name": connector.Name, + "description": connector.Description, "vpn_region_id": connector.VpnRegionId, "ip_v4_address": connector.IPv4Address, "ip_v6_address": connector.IPv6Address, diff --git a/go.mod b/go.mod index 186d5e1..46b40fd 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gruntwork-io/terratest v0.46.1 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 - github.com/openvpn/cloudconnexa-go-client/v2 v2.0.10 + github.com/openvpn/cloudconnexa-go-client/v2 v2.0.11 github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 386f0df..3908bb0 100644 --- a/go.sum +++ b/go.sum @@ -485,8 +485,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.10 h1:k5wx9syxxwNNKbfEQkVjb/4hjhBrhbgBDmeT72yNe3w= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.10/go.mod h1:udq5IDkgXvMO6mQUEFsLHzEyGGAduhO0jJvlb9f4JkE= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.11 h1:NZ5cdmKhhjIYRbmyHXvRsCUTOI4tOtPlBaXpO/PgSnI= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.11/go.mod h1:udq5IDkgXvMO6mQUEFsLHzEyGGAduhO0jJvlb9f4JkE= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From cab3054f9fceef34401d397cc5261acbf005d9bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 07:18:26 +0000 Subject: [PATCH 03/20] Bump golangci/golangci-lint-action from 6.0.1 to 6.1.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.0.1 to 6.1.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.0.1...v6.1.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 61b5d77..9aa744b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,6 +23,6 @@ jobs: cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v6.0.1 + uses: golangci/golangci-lint-action@v6.1.0 with: version: v1.55.2 From fd7733a8b707cc7eb399d014b26c576fe2fa8237 Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Tue, 30 Jul 2024 11:56:51 +0200 Subject: [PATCH 04/20] fixed connector datasource --- cloudconnexa/data_source_connector.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cloudconnexa/data_source_connector.go b/cloudconnexa/data_source_connector.go index 717faaa..aef6612 100644 --- a/cloudconnexa/data_source_connector.go +++ b/cloudconnexa/data_source_connector.go @@ -63,10 +63,15 @@ func dataSourceConnector() *schema.Resource { func dataSourceConnectorRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { c := m.(*cloudconnexa.Client) var diags diag.Diagnostics - connector, err := c.Connectors.GetByName(d.Get("name").(string)) + name := d.Get("name").(string) + connector, err := c.Connectors.GetByName(name) if err != nil { return append(diags, diag.FromErr(err)...) } + if connector == nil { + return append(diags, diag.Errorf("Connector with name %s was not found", name)...) + } + d.SetId(connector.Id) d.Set("name", connector.Name) d.Set("description", connector.Description) From bb3bc63880c0f183a70d1cb9ae43c63fc032cbb0 Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Tue, 30 Jul 2024 13:31:47 +0200 Subject: [PATCH 05/20] Added missing route description in network datasource --- cloudconnexa/data_source_network.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cloudconnexa/data_source_network.go b/cloudconnexa/data_source_network.go index d833e26..9f51371 100644 --- a/cloudconnexa/data_source_network.go +++ b/cloudconnexa/data_source_network.go @@ -62,6 +62,11 @@ func dataSourceNetwork() *schema.Resource { Computed: true, Description: "The value of the route, either an IPV4 address, an IPV6 address, or a DNS hostname.", }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the route.", + }, }, }, }, @@ -147,6 +152,7 @@ func getRoutesSlice(networkRoutes *[]cloudconnexa.Route) []interface{} { route["id"] = r.Id route["subnet"] = r.Subnet route["type"] = r.Type + route["description"] = r.Description routes[i] = route } return routes From 0df4b41d80ac73fa55fd49bdfe5a7ed321c1c53c Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Tue, 30 Jul 2024 13:41:20 +0200 Subject: [PATCH 06/20] added missing network description --- cloudconnexa/data_source_network.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cloudconnexa/data_source_network.go b/cloudconnexa/data_source_network.go index 9f51371..155517e 100644 --- a/cloudconnexa/data_source_network.go +++ b/cloudconnexa/data_source_network.go @@ -23,6 +23,11 @@ func dataSourceNetwork() *schema.Resource { Required: true, Description: "The network name.", }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the network.", + }, "egress": { Type: schema.TypeBool, Computed: true, From 265d59a2277f5123ac099c95f2540372f4d3803c Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Tue, 30 Jul 2024 13:57:02 +0200 Subject: [PATCH 07/20] [TF] Retrieve connector token --- cloudconnexa/data_source_connector.go | 11 +++++++++++ cloudconnexa/resource_connector.go | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/cloudconnexa/data_source_connector.go b/cloudconnexa/data_source_connector.go index aef6612..7e8ed18 100644 --- a/cloudconnexa/data_source_connector.go +++ b/cloudconnexa/data_source_connector.go @@ -56,6 +56,11 @@ func dataSourceConnector() *schema.Resource { Computed: true, Description: "OpenVPN profile", }, + "token": { + Type: schema.TypeString, + Computed: true, + Description: "Connector token", + }, }, } } @@ -71,6 +76,10 @@ func dataSourceConnectorRead(ctx context.Context, d *schema.ResourceData, m inte if connector == nil { return append(diags, diag.Errorf("Connector with name %s was not found", name)...) } + token, err := c.Connectors.GetToken(connector.Id) + if err != nil { + return append(diags, diag.FromErr(err)...) + } d.SetId(connector.Id) d.Set("name", connector.Name) @@ -80,6 +89,8 @@ func dataSourceConnectorRead(ctx context.Context, d *schema.ResourceData, m inte d.Set("vpn_region_id", connector.VpnRegionId) d.Set("ip_v4_address", connector.IPv4Address) d.Set("ip_v6_address", connector.IPv6Address) + d.Set("token", token) + profile, err := c.Connectors.GetProfile(connector.Id) if err != nil { return append(diags, diag.FromErr(err)...) diff --git a/cloudconnexa/resource_connector.go b/cloudconnexa/resource_connector.go index ef78191..05909f8 100644 --- a/cloudconnexa/resource_connector.go +++ b/cloudconnexa/resource_connector.go @@ -66,6 +66,11 @@ func resourceConnector() *schema.Resource { Computed: true, Description: "OpenVPN profile of the connector.", }, + "token": { + Type: schema.TypeString, + Computed: true, + Description: "Connector token.", + }, }, } } @@ -111,6 +116,11 @@ func resourceConnectorCreate(ctx context.Context, d *schema.ResourceData, m inte return append(diags, diag.FromErr(err)...) } d.Set("profile", profile) + token, err := c.Connectors.GetToken(conn.Id) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + d.Set("token", token) return append(diags, diag.Diagnostic{ Severity: diag.Warning, Summary: "Connector needs to be set up manually", @@ -125,6 +135,11 @@ func resourceConnectorRead(ctx context.Context, d *schema.ResourceData, m interf if err != nil { return append(diags, diag.FromErr(err)...) } + token, err := c.Connectors.GetToken(connector.Id) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + if connector == nil { d.SetId("") } else { @@ -135,6 +150,7 @@ func resourceConnectorRead(ctx context.Context, d *schema.ResourceData, m interf d.Set("network_item_id", connector.NetworkItemId) d.Set("ip_v4_address", connector.IPv4Address) d.Set("ip_v6_address", connector.IPv6Address) + d.Set("token", token) profile, err := c.Connectors.GetProfile(connector.Id) if err != nil { return append(diags, diag.FromErr(err)...) From a0c65acf16fdec4246e98c6038815af3c9b84ba9 Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Tue, 30 Jul 2024 13:45:07 +0200 Subject: [PATCH 08/20] FIX: [TF] Data source "host" crashing Terraform provider --- cloudconnexa/data_source_host.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cloudconnexa/data_source_host.go b/cloudconnexa/data_source_host.go index c8180b5..ccc8762 100644 --- a/cloudconnexa/data_source_host.go +++ b/cloudconnexa/data_source_host.go @@ -101,10 +101,15 @@ func dataSourceHost() *schema.Resource { func dataSourceHostRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { c := m.(*cloudconnexa.Client) var diags diag.Diagnostics - host, err := c.Hosts.GetByName(d.Get("name").(string)) + name := d.Get("name").(string) + host, err := c.Hosts.GetByName(name) if err != nil { return append(diags, diag.FromErr(err)...) } + if host == nil { + return append(diags, diag.Errorf("Host with name %s was not found", name)...) + } + d.SetId(host.Id) d.Set("name", host.Name) d.Set("description", host.Description) From eaea461d0c9512d812bbb6f830a4249fffec2d18 Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Wed, 31 Jul 2024 13:27:44 +0200 Subject: [PATCH 09/20] Added connect_auth field support in user_group datasource --- cloudconnexa/data_source_user_group.go | 6 ++++++ docs/data-sources/user_group.md | 1 + 2 files changed, 7 insertions(+) diff --git a/cloudconnexa/data_source_user_group.go b/cloudconnexa/data_source_user_group.go index 35b6fb1..8bc071c 100644 --- a/cloudconnexa/data_source_user_group.go +++ b/cloudconnexa/data_source_user_group.go @@ -49,6 +49,11 @@ func dataSourceUserGroup() *schema.Resource { }, Description: "The IPV4 and IPV6 addresses of the subnets associated with this user group.", }, + "connect_auth": { + Type: schema.TypeString, + Computed: true, + Description: "The type of connection authentication. Valid values are `AUTH`, `AUTO`, or `STRICT_AUTH`.", + }, }, } } @@ -70,5 +75,6 @@ func dataSourceUserGroupRead(ctx context.Context, d *schema.ResourceData, m inte d.Set("internet_access", userGroup.InternetAccess) d.Set("max_device", userGroup.MaxDevice) d.Set("system_subnets", userGroup.SystemSubnets) + d.Set("connect_auth", userGroup.ConnectAuth) return diags } diff --git a/docs/data-sources/user_group.md b/docs/data-sources/user_group.md index bc78035..f9a1def 100644 --- a/docs/data-sources/user_group.md +++ b/docs/data-sources/user_group.md @@ -27,3 +27,4 @@ Use an `cloudconnexa_user_group` data source to read an CloudConnexa user group. - `system_subnets` (List of String) The IPV4 and IPV6 addresses of the subnets associated with this user group. - `user_group_id` (String) The user group ID. - `vpn_region_ids` (List of String) The list of VPN region IDs this user group is associated with. +- `connect_auth` (String) The type of connection authentication. Valid values are `AUTH`, `AUTO`, or `STRICT_AUTH`. From ef6a502a60d491236bcdac883ae07f573849e608 Mon Sep 17 00:00:00 2001 From: Michael Fomenko Date: Wed, 31 Jul 2024 15:16:51 +0200 Subject: [PATCH 10/20] Added connection_status field support in user datasource (#37) * Added connection_status field support in user datasource * updated client lib --- cloudconnexa/data_source_user.go | 6 ++++++ docs/data-sources/user.md | 4 ++++ go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cloudconnexa/data_source_user.go b/cloudconnexa/data_source_user.go index c5f1a97..f4f1789 100644 --- a/cloudconnexa/data_source_user.go +++ b/cloudconnexa/data_source_user.go @@ -58,6 +58,11 @@ func dataSourceUser() *schema.Resource { Computed: true, Description: "The user's status.", }, + "connection_status": { + Type: schema.TypeString, + Computed: true, + Description: "The user's connection status.", + }, "devices": { Type: schema.TypeList, Computed: true, @@ -118,6 +123,7 @@ func dataSourceUserRead(ctx context.Context, d *schema.ResourceData, m interface d.Set("group_id", user.GroupId) d.Set("status", user.Status) d.Set("devices", getUserDevicesSlice(&user.Devices)) + d.Set("connection_status", user.ConnectionStatus) return diags } diff --git a/docs/data-sources/user.md b/docs/data-sources/user.md index 13b1357..67bfb63 100644 --- a/docs/data-sources/user.md +++ b/docs/data-sources/user.md @@ -13,6 +13,7 @@ Use a `cloudconnexa_user` data source to read a specific CloudConnexa user. + ## Schema ### Required @@ -31,8 +32,11 @@ Use a `cloudconnexa_user` data source to read a specific CloudConnexa user. - `last_name` (String) The user's last name. - `status` (String) The user's status. - `user_id` (String) The ID of this resource. +- `connection_status` (String) The user's connection status. Valid values are `OFFLINE`, `ONLINE`, + or `ONLINE_WITH_ISSUES`. + ### Nested Schema for `devices` Read-Only: diff --git a/go.mod b/go.mod index 46b40fd..f016f5e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gruntwork-io/terratest v0.46.1 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 - github.com/openvpn/cloudconnexa-go-client/v2 v2.0.11 + github.com/openvpn/cloudconnexa-go-client/v2 v2.0.12 github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 3908bb0..1908c42 100644 --- a/go.sum +++ b/go.sum @@ -485,8 +485,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.11 h1:NZ5cdmKhhjIYRbmyHXvRsCUTOI4tOtPlBaXpO/PgSnI= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.11/go.mod h1:udq5IDkgXvMO6mQUEFsLHzEyGGAduhO0jJvlb9f4JkE= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.12 h1:qUgOw8ppxtUj741XqfVCbtSNHBM81J6cEQkr3hgs9Jg= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.12/go.mod h1:udq5IDkgXvMO6mQUEFsLHzEyGGAduhO0jJvlb9f4JkE= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From 1a7892e0a8c3721c4e63f0d60667876a9fc86734 Mon Sep 17 00:00:00 2001 From: Vlad H Date: Wed, 31 Jul 2024 19:17:06 +0300 Subject: [PATCH 11/20] Extend custom service types in IP services (#34) * Extend custom service types in IP services * Add Import for ip services --------- Co-authored-by: vladhanzha Co-authored-by: Oleksandr Lytvyn --- cloudconnexa/resource_application.go | 20 +++- cloudconnexa/resource_service.go | 143 +++++++++++++++------------ docs/data-sources/ip_service.md | 14 +-- docs/resources/ip_service.md | 13 +-- example/applications.tf | 4 +- example/services.tf | 65 +++++++++++- 6 files changed, 171 insertions(+), 88 deletions(-) diff --git a/cloudconnexa/resource_application.go b/cloudconnexa/resource_application.go index 4e36d05..d8b72bf 100644 --- a/cloudconnexa/resource_application.go +++ b/cloudconnexa/resource_application.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" + "slices" ) func resourceApplication() *schema.Resource { @@ -92,7 +93,7 @@ func resourceApplicationConfig() *schema.Resource { Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ - Schema: customServiceTypesConfig(), + Schema: customApplicationTypesConfig(), }, }, "service_types": { @@ -116,7 +117,7 @@ func resourceApplicationConfig() *schema.Resource { } } -func customServiceTypesConfig() map[string]*schema.Schema { +func customApplicationTypesConfig() map[string]*schema.Schema { return map[string]*schema.Schema{ "protocol": { Type: schema.TypeString, @@ -172,7 +173,7 @@ func resourceApplicationDelete(ctx context.Context, data *schema.ResourceData, i func flattenApplicationConfig(config *cloudconnexa.ApplicationConfig) interface{} { var data = map[string]interface{}{ "custom_service_types": flattenApplicationCustomTypes(config.CustomServiceTypes), - "service_types": config.ServiceTypes, + "service_types": removeElement(config.ServiceTypes, "CUSTOM"), } return []interface{}{data} } @@ -285,6 +286,9 @@ func resourceDataToApplication(data *schema.ResourceData) *cloudconnexa.Applicat for _, r := range mainConfig["service_types"].([]interface{}) { config.ServiceTypes = append(config.ServiceTypes, r.(string)) } + if len(config.CustomServiceTypes) > 0 && !slices.Contains(config.ServiceTypes, "CUSTOM") { + config.ServiceTypes = append(config.ServiceTypes, "CUSTOM") + } } s := &cloudconnexa.Application{ @@ -297,3 +301,13 @@ func resourceDataToApplication(data *schema.ResourceData) *cloudconnexa.Applicat } return s } + +func removeElement(slice []string, element string) []string { + var result []string + for _, item := range slice { + if item != element { + result = append(result, item) + } + } + return result +} diff --git a/cloudconnexa/resource_service.go b/cloudconnexa/resource_service.go index cc3d045..6de5c62 100644 --- a/cloudconnexa/resource_service.go +++ b/cloudconnexa/resource_service.go @@ -2,6 +2,7 @@ package cloudconnexa import ( "context" + "slices" "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -11,7 +12,7 @@ import ( ) var ( - validValues = []string{"ANY", "BGP", "CUSTOM", "DHCP", "DNS", "FTP", "HTTP", "HTTPS", "IMAP", "IMAPS", "NTP", "POP3", "POP3S", "SMTP", "SMTPS", "SNMP", "SSH", "TELNET", "TFTP"} + validValues = []string{"ANY", "BGP", "DHCP", "DNS", "FTP", "HTTP", "HTTPS", "IMAP", "IMAPS", "NTP", "POP3", "POP3S", "SMTP", "SMTPS", "SNMP", "SSH", "TELNET", "TFTP"} ) func resourceIPService() *schema.Resource { @@ -20,6 +21,9 @@ func resourceIPService() *schema.Resource { ReadContext: resourceServiceRead, DeleteContext: resourceServiceDelete, UpdateContext: resourceServiceUpdate, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, Schema: map[string]*schema.Schema{ "id": { Type: schema.TypeString, @@ -31,7 +35,7 @@ func resourceIPService() *schema.Resource { }, "description": { Type: schema.TypeString, - Default: "Created by Terraform CloudConnexa Provider", + Default: "Managed by Terraform", ValidateFunc: validation.StringLenBetween(1, 255), Optional: true, }, @@ -42,8 +46,7 @@ func resourceIPService() *schema.Resource { }, "routes": { Type: schema.TypeList, - Required: true, - MinItems: 1, + Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -82,27 +85,10 @@ func resourceServiceConfig() *schema.Resource { return &schema.Resource{ Schema: map[string]*schema.Schema{ "custom_service_types": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "icmp_type": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "lower_value": { - Type: schema.TypeInt, - Required: true, - }, - "upper_value": { - Type: schema.TypeInt, - Required: true, - }, - }, - }, - }, - }, + Schema: customServiceTypesConfig(), }, }, "service_types": { @@ -126,6 +112,24 @@ func resourceServiceConfig() *schema.Resource { } } +func customServiceTypesConfig() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "protocol": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"TCP", "UDP", "ICMP"}, false), + }, + "from_port": { + Type: schema.TypeInt, + Optional: true, + }, + "to_port": { + Type: schema.TypeInt, + Optional: true, + }, + } +} + func resourceServiceRead(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics { c := i.(*cloudconnexa.Client) var diags diag.Diagnostics @@ -165,36 +169,30 @@ func resourceServiceDelete(ctx context.Context, data *schema.ResourceData, i int func flattenServiceConfig(config *cloudconnexa.IPServiceConfig) interface{} { var data = map[string]interface{}{ "custom_service_types": flattenCustomServiceTypes(config.CustomServiceTypes), - "service_types": config.ServiceTypes, + "service_types": removeElement(config.ServiceTypes, "CUSTOM"), } return []interface{}{data} } func flattenCustomServiceTypes(types []*cloudconnexa.CustomIPServiceType) interface{} { - var data []interface{} + var cst []interface{} for _, t := range types { - data = append( - data, - map[string]interface{}{ - "icmp_type": flattenIcmpType(t.IcmpType), - }, - ) - } - return data -} - -func flattenIcmpType(icmpType []cloudconnexa.Range) interface{} { - var data []interface{} - for _, t := range icmpType { - data = append( - data, - map[string]interface{}{ - "lower_value": t.LowerValue, - "upper_value": t.UpperValue, - }, - ) + var ports = append(t.Port, t.IcmpType...) + if len(ports) > 0 { + for _, port := range ports { + cst = append(cst, map[string]interface{}{ + "protocol": t.Protocol, + "from_port": port.LowerValue, + "to_port": port.UpperValue, + }) + } + } else { + cst = append(cst, map[string]interface{}{ + "protocol": t.Protocol, + }) + } } - return data + return cst } func flattenRoutes(routes []*cloudconnexa.Route) []string { @@ -241,30 +239,51 @@ func resourceDataToService(data *schema.ResourceData) *cloudconnexa.IPService { config.ServiceTypes = []string{} mainConfig := configList[0].(map[string]interface{}) - for _, r := range mainConfig["custom_service_types"].([]interface{}) { - cst := r.(map[string]interface{}) - var icmpTypes []cloudconnexa.Range - for _, r := range cst["icmp_type"].([]interface{}) { - icmpType := r.(map[string]interface{}) - icmpTypes = append( - icmpTypes, - cloudconnexa.Range{ - LowerValue: icmpType["lower_value"].(int), - UpperValue: icmpType["upper_value"].(int), + var cst = mainConfig["custom_service_types"].(*schema.Set) + var groupedCst = make(map[string][]cloudconnexa.Range) + for _, item := range cst.List() { + var cstItem = item.(map[string]interface{}) + var protocol = cstItem["protocol"].(string) + var fromPort = cstItem["from_port"].(int) + var toPort = cstItem["to_port"].(int) + + if groupedCst[protocol] == nil { + groupedCst[protocol] = make([]cloudconnexa.Range, 0) + } + if fromPort > 0 || toPort > 0 { + groupedCst[protocol] = append(groupedCst[protocol], cloudconnexa.Range{ + LowerValue: fromPort, + UpperValue: toPort, + }) + } + } + + for protocol, ports := range groupedCst { + if protocol == "ICMP" { + config.CustomServiceTypes = append( + config.CustomServiceTypes, + &cloudconnexa.CustomIPServiceType{ + Protocol: protocol, + IcmpType: ports, + }, + ) + } else { + config.CustomServiceTypes = append( + config.CustomServiceTypes, + &cloudconnexa.CustomIPServiceType{ + Protocol: protocol, + Port: ports, }, ) } - config.CustomServiceTypes = append( - config.CustomServiceTypes, - &cloudconnexa.CustomIPServiceType{ - IcmpType: icmpTypes, - }, - ) } for _, r := range mainConfig["service_types"].([]interface{}) { config.ServiceTypes = append(config.ServiceTypes, r.(string)) } + if len(config.CustomServiceTypes) > 0 && !slices.Contains(config.ServiceTypes, "CUSTOM") { + config.ServiceTypes = append(config.ServiceTypes, "CUSTOM") + } } s := &cloudconnexa.IPService{ diff --git a/docs/data-sources/ip_service.md b/docs/data-sources/ip_service.md index 2041b37..75352fa 100644 --- a/docs/data-sources/ip_service.md +++ b/docs/data-sources/ip_service.md @@ -31,7 +31,7 @@ description: |- Read-Only: -- `custom_service_types` (List of Object) (see [below for nested schema](#nestedobjatt--config--custom_service_types)) +- `custom_service_types` (Set of Object) (see [below for nested schema](#nestedobjatt--config--custom_service_types)) - `service_types` (List of String) @@ -39,12 +39,6 @@ Read-Only: Read-Only: -- `icmp_type` (List of Object) (see [below for nested schema](#nestedobjatt--config--custom_service_types--icmp_type)) - - -### Nested Schema for `config.custom_service_types.icmp_type` - -Read-Only: - -- `lower_value` (Number) -- `upper_value` (Number) +- `from_port` (Number) +- `protocol` (String) +- `to_port` (Number) diff --git a/docs/resources/ip_service.md b/docs/resources/ip_service.md index 9654588..4775f7b 100644 --- a/docs/resources/ip_service.md +++ b/docs/resources/ip_service.md @@ -37,7 +37,7 @@ description: |- Optional: -- `custom_service_types` (Block List) (see [below for nested schema](#nestedblock--config--custom_service_types)) +- `custom_service_types` (Block Set) (see [below for nested schema](#nestedblock--config--custom_service_types)) - `service_types` (List of String) @@ -45,12 +45,9 @@ Optional: Required: -- `icmp_type` (Block List, Min: 1) (see [below for nested schema](#nestedblock--config--custom_service_types--icmp_type)) +- `protocol` (String) - -### Nested Schema for `config.custom_service_types.icmp_type` - -Required: +Optional: -- `lower_value` (Number) -- `upper_value` (Number) +- `from_port` (Number) +- `to_port` (Number) diff --git a/example/applications.tf b/example/applications.tf index d314a78..2451dfd 100644 --- a/example/applications.tf +++ b/example/applications.tf @@ -27,7 +27,7 @@ resource "cloudconnexa_application" "application_custom_access" { } config { - service_types = ["HTTP", "HTTPS", "CUSTOM"] + service_types = ["HTTP", "HTTPS"] custom_service_types { protocol = "TCP" //all tcp ports } @@ -55,7 +55,7 @@ resource "cloudconnexa_application" "application_custom_access" { } locals { - created_by = "managed by terraform" + created_by = "Managed by terraform" } variable "application_custom_access_advanced" { diff --git a/example/services.tf b/example/services.tf index 30d6d21..46b9201 100644 --- a/example/services.tf +++ b/example/services.tf @@ -2,15 +2,74 @@ data "cloudconnexa_network" "test-net" { name = "test-net" } -resource "cloudconnexa_ip_service" "test-service" { - name = "test-service" +resource "cloudconnexa_ip_service" "service_full_access" { + name = "example-service-1" type = "IP_SOURCE" description = "test-description" routes = ["10.0.0.2/32"] network_item_type = "NETWORK" network_item_id = data.cloudconnexa_network.test-net.id - config { service_types = ["ANY"] } } + +resource "cloudconnexa_ip_service" "service_custom_access" { + name = "example-service-2" + type = "IP_SOURCE" + network_item_type = "NETWORK" + network_item_id = data.cloudconnexa_network.test-net.id + routes = ["10.0.0.2/32"] + config { + service_types = ["HTTP", "HTTPS"] + custom_service_types { + protocol = "TCP" //all tcp ports + } + custom_service_types { + protocol = "UDP" + from_port = 1194 + to_port = 1194 + } + custom_service_types { + protocol = "UDP" + from_port = 5000 + to_port = 5010 + } + custom_service_types { + protocol = "ICMP" + from_port = 8 + to_port = 8 + } + custom_service_types { + protocol = "ICMP" + from_port = 20 + to_port = 22 + } + } +} + +locals { + created_by = "Managed by terraform" +} + +variable "service_custom_access_advanced" { + description = "xxx" + type = any + default = { + "example-service-3" = { route = ["10.0.0.3/32", "10.0.1.3/32"] } + "example-service-4" = { route = ["10.0.0.4/32"] } + } +} + +resource "cloudconnexa_ip_service" "service_custom_access_advanced" { + for_each = var.service_custom_access_advanced + name = each.key + type = "SERVICE_DESTINATION" + description = try(each.value.description, local.created_by) + network_item_type = "NETWORK" + network_item_id = data.cloudconnexa_network.test-net.id + routes = each.value.route + config { + service_types = ["ANY"] + } +} \ No newline at end of file From 4fe69523b3c01158d5ff734b11be692c15cfc0a6 Mon Sep 17 00:00:00 2001 From: Michael Fomenko Date: Thu, 1 Aug 2024 13:43:52 +0200 Subject: [PATCH 12/20] Removed automatic default group id search on user creation (#35) * removed automatic default user group id * group_id made required & validated field in user datasource * group_id made required & validated field in user resource --- cloudconnexa/resource_user.go | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/cloudconnexa/resource_user.go b/cloudconnexa/resource_user.go index c6ea9db..dea5e51 100644 --- a/cloudconnexa/resource_user.go +++ b/cloudconnexa/resource_user.go @@ -2,7 +2,6 @@ package cloudconnexa import ( "context" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -46,9 +45,10 @@ func resourceUser() *schema.Resource { Description: "User's last name.", }, "group_id": { - Type: schema.TypeString, - Optional: true, - Description: "The UUID of a user's group.", + Type: schema.TypeString, + Required: true, + Description: "The UUID of a user's group.", + ValidateFunc: validation.IsUUID, }, "role": { Type: schema.TypeString, @@ -145,16 +145,6 @@ func resourceUserRead(ctx context.Context, d *schema.ResourceData, m interface{} userId := d.Id() u, err := c.Users.Get(userId) - // If group_id is not set, CloudConnexa sets it to the default group. - var groupId string - if d.Get("group_id") == "" { - // The group has not been explicitly set. - // Set it to an empty string to keep the default group. - groupId = "" - } else { - groupId = u.GroupId - } - if err != nil { return append(diags, diag.FromErr(err)...) } @@ -165,7 +155,7 @@ func resourceUserRead(ctx context.Context, d *schema.ResourceData, m interface{} d.Set("email", u.Email) d.Set("first_name", u.FirstName) d.Set("last_name", u.LastName) - d.Set("group_id", groupId) + d.Set("group_id", u.GroupId) d.Set("devices", u.Devices) d.Set("role", u.Role) } @@ -189,25 +179,14 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, m interface _, lastName := d.GetChange("last_name") _, role := d.GetChange("role") status := u.Status - oldGroupId, newGroupId := d.GetChange("group_id") - - groupId := newGroupId.(string) - // If both are empty strings, then the group has not been set explicitly. - // The update endpoint requires group_id to be set, so we should set it to the default group. - if oldGroupId.(string) == "" && groupId == "" { - g, err := c.UserGroups.GetByName("Default") - if err != nil { - return append(diags, diag.FromErr(err)...) - } - groupId = g.ID - } + _, groupId := d.GetChange("group_id") err = c.Users.Update(cloudconnexa.User{ Id: d.Id(), Email: email.(string), FirstName: firstName.(string), LastName: lastName.(string), - GroupId: groupId, + GroupId: groupId.(string), Role: role.(string), Status: status, }) From 731a6f2e2db60c1383621420f73dbced7fa649d1 Mon Sep 17 00:00:00 2001 From: Oleksandr Lytvyn Date: Thu, 1 Aug 2024 15:20:46 +0300 Subject: [PATCH 13/20] Fix cloudconnexa_vpn_region data source (#39) --- cloudconnexa/data_source_vpn_region.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cloudconnexa/data_source_vpn_region.go b/cloudconnexa/data_source_vpn_region.go index 550a265..48c343b 100644 --- a/cloudconnexa/data_source_vpn_region.go +++ b/cloudconnexa/data_source_vpn_region.go @@ -2,6 +2,7 @@ package cloudconnexa import ( "context" + "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -45,7 +46,7 @@ func dataSourceVpnRegion() *schema.Resource { func dataSourceVpnRegionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { c := m.(*cloudconnexa.Client) var diags diag.Diagnostics - vpnRegionId := d.Get("region_id").(string) + vpnRegionId := d.Get("id").(string) vpnRegion, err := c.VPNRegions.GetVpnRegion(vpnRegionId) if err != nil { return append(diags, diag.FromErr(err)...) From 713dd4676430d29a4ebc6680cf7f169ed3ca5fee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:24:31 +0300 Subject: [PATCH 14/20] Bump github.com/hashicorp/go-getter in the go_modules group (#28) Bumps the go_modules group with 1 update: [github.com/hashicorp/go-getter](https://github.com/hashicorp/go-getter). Updates `github.com/hashicorp/go-getter` from 1.7.4 to 1.7.5 - [Release notes](https://github.com/hashicorp/go-getter/releases) - [Changelog](https://github.com/hashicorp/go-getter/blob/main/.goreleaser.yml) - [Commits](https://github.com/hashicorp/go-getter/compare/v1.7.4...v1.7.5) --- updated-dependencies: - dependency-name: github.com/hashicorp/go-getter dependency-type: indirect dependency-group: go_modules ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f016f5e..18dfc85 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.4 // indirect + github.com/hashicorp/go-getter v1.7.5 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect diff --git a/go.sum b/go.sum index 1908c42..5c3ff7b 100644 --- a/go.sum +++ b/go.sum @@ -388,8 +388,8 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0= -github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-getter v1.7.5 h1:dT58k9hQ/vbxNMwoI5+xFYAJuv6152UNvdHokfI5wE4= +github.com/hashicorp/go-getter v1.7.5/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= From 021c9be0cc33cb00fcfc70e969cc388f97002076 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:27:52 +0300 Subject: [PATCH 15/20] Bump github.com/gruntwork-io/terratest from 0.46.1 to 0.47.0 (#23) Bumps [github.com/gruntwork-io/terratest](https://github.com/gruntwork-io/terratest) from 0.46.1 to 0.47.0. - [Release notes](https://github.com/gruntwork-io/terratest/releases) - [Commits](https://github.com/gruntwork-io/terratest/compare/v0.46.1...v0.47.0) --- updated-dependencies: - dependency-name: github.com/gruntwork-io/terratest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 18dfc85..7e44929 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 toolchain go1.21.3 require ( - github.com/gruntwork-io/terratest v0.46.1 + github.com/gruntwork-io/terratest v0.47.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/openvpn/cloudconnexa-go-client/v2 v2.0.12 diff --git a/go.sum b/go.sum index 5c3ff7b..5f5d878 100644 --- a/go.sum +++ b/go.sum @@ -376,8 +376,8 @@ github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56 github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/gruntwork-io/terratest v0.46.1 h1:dJ/y2/Li6yCDIc8KXY8PfydtrMRiXFb3UZm4LoPShPI= -github.com/gruntwork-io/terratest v0.46.1/go.mod h1:gl//tb5cLnbpQs1FTSNwhsrbhsoG00goCJPfOnyliiU= +github.com/gruntwork-io/terratest v0.47.0 h1:xIy1pT7NbGVlMLDZEHl3+3iSnvffh8tN2pL6idn448c= +github.com/gruntwork-io/terratest v0.47.0/go.mod h1:oywHw1cFKXSYvKPm27U7quZVzDUlA22H2xUrKCe26xM= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -496,8 +496,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= From d3c6d6129f89c9d8fa67e8e0674ad9ec4a8d955b Mon Sep 17 00:00:00 2001 From: Oleksandr Lytvyn Date: Mon, 5 Aug 2024 12:16:37 +0300 Subject: [PATCH 16/20] Update cloudconnexa_user resource (#40) * Update cloudconnexa_user resource --- cloudconnexa/resource_user.go | 24 ++++++++++++------------ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cloudconnexa/resource_user.go b/cloudconnexa/resource_user.go index dea5e51..e21ccb0 100644 --- a/cloudconnexa/resource_user.go +++ b/cloudconnexa/resource_user.go @@ -2,6 +2,7 @@ package cloudconnexa import ( "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -28,19 +29,19 @@ func resourceUser() *schema.Resource { }, "email": { Type: schema.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringLenBetween(1, 120), Description: "An invitation to CloudConnexa account will be sent to this email. It will include an initial password and a VPN setup guide.", }, "first_name": { Type: schema.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringLenBetween(1, 20), Description: "User's first name.", }, "last_name": { Type: schema.TypeString, - Required: true, + Optional: true, ValidateFunc: validation.StringLenBetween(1, 20), Description: "User's last name.", }, @@ -53,7 +54,6 @@ func resourceUser() *schema.Resource { "role": { Type: schema.TypeString, Optional: true, - ForceNew: true, Default: "MEMBER", Description: "The type of user role. Valid values are `ADMIN`, `MEMBER`, or `OWNER`.", }, @@ -132,11 +132,7 @@ func resourceUserCreate(ctx context.Context, d *schema.ResourceData, m interface return append(diags, diag.FromErr(err)...) } d.SetId(user.Id) - return append(diags, diag.Diagnostic{ - Severity: diag.Warning, - Summary: "The user's role cannot be changed using the code.", - Detail: "There is a bug in CloudConnexa API that prevents setting the user's role during the creation. All users are created as Members by default. Once it's fixed, the provider will be updated accordingly.", - }) + return diags } func resourceUserRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { @@ -165,7 +161,7 @@ func resourceUserRead(ctx context.Context, d *schema.ResourceData, m interface{} func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { c := m.(*cloudconnexa.Client) var diags diag.Diagnostics - if !d.HasChanges("first_name", "last_name", "group_id", "email") { + if !d.HasChanges("first_name", "last_name", "group_id", "email", "role") { return diags } @@ -178,8 +174,8 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, m interface _, firstName := d.GetChange("first_name") _, lastName := d.GetChange("last_name") _, role := d.GetChange("role") - status := u.Status _, groupId := d.GetChange("group_id") + status := u.Status err = c.Users.Update(cloudconnexa.User{ Id: d.Id(), @@ -191,7 +187,11 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, m interface Status: status, }) - return append(diags, diag.FromErr(err)...) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + + return diags } func resourceUserDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { diff --git a/go.mod b/go.mod index 7e44929..036d6c8 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gruntwork-io/terratest v0.47.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 - github.com/openvpn/cloudconnexa-go-client/v2 v2.0.12 + github.com/openvpn/cloudconnexa-go-client/v2 v2.0.13 github.com/stretchr/testify v1.9.0 ) diff --git a/go.sum b/go.sum index 5f5d878..bb2908a 100644 --- a/go.sum +++ b/go.sum @@ -485,8 +485,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.12 h1:qUgOw8ppxtUj741XqfVCbtSNHBM81J6cEQkr3hgs9Jg= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.12/go.mod h1:udq5IDkgXvMO6mQUEFsLHzEyGGAduhO0jJvlb9f4JkE= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.13 h1:Bm47oT/O+CwXdwUu84NZZXETZCo/9Th3Cx+EGUXvyPU= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.13/go.mod h1:udq5IDkgXvMO6mQUEFsLHzEyGGAduhO0jJvlb9f4JkE= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From eac7aa72c48984fe293e956465356a3f5980c01e Mon Sep 17 00:00:00 2001 From: Olexandr Lytvyn Date: Mon, 5 Aug 2024 13:07:31 +0300 Subject: [PATCH 17/20] Update examples and documentation --- docs/data-sources/application.md | 12 +++++++++++- docs/data-sources/connector.md | 2 ++ docs/data-sources/user.md | 4 ---- docs/data-sources/user_group.md | 5 ++--- docs/data-sources/vpn_region.md | 3 +-- docs/resources/ip_service.md | 2 +- example/applications.tf | 4 ++-- example/networks.tf | 2 +- example/routes.tf | 2 +- example/variables.tf | 10 +++++----- 10 files changed, 26 insertions(+), 20 deletions(-) diff --git a/docs/data-sources/application.md b/docs/data-sources/application.md index d9094d1..e7706f4 100644 --- a/docs/data-sources/application.md +++ b/docs/data-sources/application.md @@ -26,7 +26,7 @@ description: |- - `id` (String) The ID of this resource. - `network_item_id` (String) - `network_item_type` (String) -- `routes` (List of String) +- `routes` (List of Object) (see [below for nested schema](#nestedatt--routes)) ### Nested Schema for `config` @@ -44,3 +44,13 @@ Read-Only: - `from_port` (Number) - `protocol` (String) - `to_port` (Number) + + + + +### Nested Schema for `routes` + +Read-Only: + +- `allow_embedded_ip` (Boolean) +- `domain` (String) diff --git a/docs/data-sources/connector.md b/docs/data-sources/connector.md index 6d7c01c..3adf5dd 100644 --- a/docs/data-sources/connector.md +++ b/docs/data-sources/connector.md @@ -21,10 +21,12 @@ Use an `cloudconnexa_connector` data source to read an existing CloudConnexa con ### Read-Only +- `description` (String) The description of the connector. - `id` (String) The ID of this resource. - `ip_v4_address` (String) The IPV4 address of the connector. - `ip_v6_address` (String) The IPV6 address of the connector. - `network_item_id` (String) The id of the network or host with which the connector is associated. - `network_item_type` (String) The network object type of the connector. This typically will be set to either `NETWORK` or `HOST`. - `profile` (String) OpenVPN profile +- `token` (String) Connector token - `vpn_region_id` (String) The id of the region where the connector is deployed. diff --git a/docs/data-sources/user.md b/docs/data-sources/user.md index 67bfb63..13b1357 100644 --- a/docs/data-sources/user.md +++ b/docs/data-sources/user.md @@ -13,7 +13,6 @@ Use a `cloudconnexa_user` data source to read a specific CloudConnexa user. - ## Schema ### Required @@ -32,11 +31,8 @@ Use a `cloudconnexa_user` data source to read a specific CloudConnexa user. - `last_name` (String) The user's last name. - `status` (String) The user's status. - `user_id` (String) The ID of this resource. -- `connection_status` (String) The user's connection status. Valid values are `OFFLINE`, `ONLINE`, - or `ONLINE_WITH_ISSUES`. - ### Nested Schema for `devices` Read-Only: diff --git a/docs/data-sources/user_group.md b/docs/data-sources/user_group.md index f9a1def..1a381f9 100644 --- a/docs/data-sources/user_group.md +++ b/docs/data-sources/user_group.md @@ -21,10 +21,9 @@ Use an `cloudconnexa_user_group` data source to read an CloudConnexa user group. ### Read-Only -- `id` (String) The ID of this resource. +- `connect_auth` (String) The type of connection authentication. Valid values are `AUTH`, `AUTO`, or `STRICT_AUTH`. +- `id` (String) The user group ID. - `internet_access` (String) The type of internet access provided. Valid values are `BLOCKED`, `GLOBAL_INTERNET`, or `LOCAL`. Defaults to `LOCAL`. - `max_device` (Number) The maximum number of devices per user. - `system_subnets` (List of String) The IPV4 and IPV6 addresses of the subnets associated with this user group. -- `user_group_id` (String) The user group ID. - `vpn_region_ids` (List of String) The list of VPN region IDs this user group is associated with. -- `connect_auth` (String) The type of connection authentication. Valid values are `AUTH`, `AUTO`, or `STRICT_AUTH`. diff --git a/docs/data-sources/vpn_region.md b/docs/data-sources/vpn_region.md index 8530a7b..ab3acf3 100644 --- a/docs/data-sources/vpn_region.md +++ b/docs/data-sources/vpn_region.md @@ -17,12 +17,11 @@ Use a `cloudconnexa_vpn_region` data source to read an CloudConnexa VPN region. ### Required -- `region_id` (String) The id of the region. +- `id` (String) The id of the region. ### Read-Only - `continent` (String) The continent of the region. - `country` (String) The country of the region. - `country_iso` (String) The ISO code of the country of the region. -- `id` (String) The ID of this resource. - `region_name` (String) The name of the region. diff --git a/docs/resources/ip_service.md b/docs/resources/ip_service.md index 4775f7b..b326a79 100644 --- a/docs/resources/ip_service.md +++ b/docs/resources/ip_service.md @@ -20,13 +20,13 @@ description: |- - `name` (String) - `network_item_id` (String) - `network_item_type` (String) -- `routes` (List of String) - `type` (String) ### Optional - `config` (Block List, Max: 1) (see [below for nested schema](#nestedblock--config)) - `description` (String) +- `routes` (List of String) ### Read-Only diff --git a/example/applications.tf b/example/applications.tf index 2451dfd..51ed7cd 100644 --- a/example/applications.tf +++ b/example/applications.tf @@ -7,7 +7,7 @@ resource "cloudconnexa_application" "application_full_access" { network_item_type = "NETWORK" network_item_id = data.cloudconnexa_network.test-net.id routes { - domain = "example-application-1.com" + domain = "example-application-1.com" allow_embedded_ip = false } @@ -22,7 +22,7 @@ resource "cloudconnexa_application" "application_custom_access" { network_item_id = data.cloudconnexa_network.test-net.id routes { - domain = "example-application-2.com" + domain = "example-application-2.com" allow_embedded_ip = false } diff --git a/example/networks.tf b/example/networks.tf index 3920eb1..b340a10 100644 --- a/example/networks.tf +++ b/example/networks.tf @@ -2,7 +2,7 @@ resource "cloudconnexa_network" "test-network" { name = "test-network" egress = false default_route { - value = "192.168.0.0/24" + subnet = "192.168.0.0/24" } default_connector { name = "test-connector" diff --git a/example/routes.tf b/example/routes.tf index cb325be..877d97a 100644 --- a/example/routes.tf +++ b/example/routes.tf @@ -4,6 +4,6 @@ resource "cloudconnexa_route" "this" { } network_item_id = var.networks["example-network"] type = "IP_V4" - subnet = each.value.subnet + subnet = each.value.subnet description = each.value.description } diff --git a/example/variables.tf b/example/variables.tf index 8169811..95bdead 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -14,13 +14,13 @@ variable "users" { }) ) default = { - "Username1" = { + "John_Doe" = { username = "Username1" email = "username1@company.com" group = "Default" role = "ADMIN" } - "Username2" = { + "Jane_Doe" = { username = "Username2" email = "username2@company.com" group = "Developer" @@ -55,15 +55,15 @@ variable "routes" { type = list(map(string)) default = [ { - subnet = "10.0.0.0/18" + subnet = "10.0.0.0/18" description = "Example Route with subnet /18" }, { - subnet = "10.10.0.0/20" + subnet = "10.10.0.0/20" description = "Example Route with subnet /20" }, { - subnet = "10.20.0.0/24" + subnet = "10.20.0.0/24" description = "Example Route with subnet /24" }, ] From a73652c9377016dce389ecbfccb913f642103143 Mon Sep 17 00:00:00 2001 From: michaelfmnk Date: Thu, 8 Aug 2024 12:53:31 +0200 Subject: [PATCH 18/20] removed client_test.go (moved to client repository) --- client/client_test.go | 104 ------------------------------------------ 1 file changed, 104 deletions(-) delete mode 100644 client/client_test.go diff --git a/client/client_test.go b/client/client_test.go deleted file mode 100644 index 84d252c..0000000 --- a/client/client_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package client - -import ( - "fmt" - "os" - "testing" - - "github.com/openvpn/cloudconnexa-go-client/v2/cloudconnexa" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func validateEnvVars(t *testing.T) { - validateEnvVar(t, HostEnvVar) - validateEnvVar(t, ClientIDEnvVar) - validateEnvVar(t, ClientSecretEnvVar) -} - -func validateEnvVar(t *testing.T, envVar string) { - fmt.Println(os.Getenv(envVar)) - require.NotEmptyf(t, os.Getenv(envVar), "%s must be set", envVar) -} - -const ( - HostEnvVar = "OVPN_HOST" - ClientIDEnvVar = "CLOUDCONNEXA_CLIENT_ID" - ClientSecretEnvVar = "CLOUDCONNEXA_CLIENT_SECRET" -) - -func TestNewClient(t *testing.T) { - c := setUpClient(t) - assert.NotEmpty(t, c.Token) -} - -func setUpClient(t *testing.T) *cloudconnexa.Client { - validateEnvVars(t) - var err error - client, err := cloudconnexa.NewClient(os.Getenv(HostEnvVar), os.Getenv(ClientIDEnvVar), os.Getenv(ClientSecretEnvVar)) - require.NoError(t, err) - return client -} - -func TestListNetworks(t *testing.T) { - c := setUpClient(t) - response, err := c.Networks.GetByPage(0, 10) - require.NoError(t, err) - fmt.Printf("found %d networks\n", len(response.Content)) -} - -func TestListConnectors(t *testing.T) { - c := setUpClient(t) - response, err := c.Connectors.GetByPage(0, 10) - require.NoError(t, err) - fmt.Printf("found %d connectors\n", len(response.Content)) -} - -func TestCreateNetwork(t *testing.T) { - c := setUpClient(t) - connector := cloudconnexa.NetworkConnector{ - Description: "test", - Name: "test", - VpnRegionId: "it-mxp", - } - route := cloudconnexa.Route{ - Description: "test", - Type: "IP_V4", - Subnet: "10.189.253.64/30", - } - network := cloudconnexa.Network{ - Description: "test", - Egress: false, - Name: "test", - InternetAccess: "LOCAL", - Connectors: []cloudconnexa.NetworkConnector{connector}, - } - response, err := c.Networks.Create(network) - require.NoError(t, err) - fmt.Printf("created %s network\n", response.Id) - test, err := c.Routes.Create(response.Id, route) - require.NoError(t, err) - fmt.Printf("created %s route\n", test.Id) - serviceConfig := cloudconnexa.IPServiceConfig{ - ServiceTypes: []string{"ANY"}, - } - ipServiceRoute := cloudconnexa.IPServiceRoute{ - Description: "test", - Value: "10.189.253.64/30", - } - service := cloudconnexa.IPService{ - Name: "test", - Description: "test", - NetworkItemId: response.Id, - Type: "IP_SOURCE", - NetworkItemType: "NETWORK", - Config: &serviceConfig, - Routes: []*cloudconnexa.IPServiceRoute{&ipServiceRoute}, - } - s, err := c.IPServices.Create(&service) - require.NoError(t, err) - fmt.Printf("created %s service\n", s.Id) - err = c.Networks.Delete(response.Id) - require.NoError(t, err) - fmt.Printf("deleted %s network\n", response.Id) -} From 3bc4984dc1580dda40d47a04da0ce10b7668294c Mon Sep 17 00:00:00 2001 From: Vlad H Date: Thu, 22 Aug 2024 17:16:06 +0300 Subject: [PATCH 19/20] Allow to select all regions for a user group (#44) * Allow to select all regions for a user group * Allow to set `allRegionsIncluded` explicitly in user group * Use ExactlyOneOf for vpn_region_ids and all_regions_included * Clear dependencies --------- Co-authored-by: vladhanzha --- cloudconnexa/data_source_user_group.go | 8 ++++++- cloudconnexa/resource_user_group.go | 30 +++++++++++++++++--------- docs/data-sources/user_group.md | 3 ++- docs/resources/user_group.md | 3 ++- go.mod | 4 ++-- go.sum | 8 +++---- 6 files changed, 37 insertions(+), 19 deletions(-) diff --git a/cloudconnexa/data_source_user_group.go b/cloudconnexa/data_source_user_group.go index 8bc071c..f4849c8 100644 --- a/cloudconnexa/data_source_user_group.go +++ b/cloudconnexa/data_source_user_group.go @@ -29,7 +29,12 @@ func dataSourceUserGroup() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, - Description: "The list of VPN region IDs this user group is associated with.", + Description: "The list of region IDs this user group is associated with.", + }, + "all_regions_included": { + Type: schema.TypeBool, + Computed: true, + Description: "If true all regions will be available for this user group.", }, "internet_access": { Type: schema.TypeString, @@ -72,6 +77,7 @@ func dataSourceUserGroupRead(ctx context.Context, d *schema.ResourceData, m inte d.SetId(userGroup.ID) d.Set("name", userGroup.Name) d.Set("vpn_region_ids", userGroup.VpnRegionIds) + d.Set("all_regions_included", userGroup.AllRegionsIncluded) d.Set("internet_access", userGroup.InternetAccess) d.Set("max_device", userGroup.MaxDevice) d.Set("system_subnets", userGroup.SystemSubnets) diff --git a/cloudconnexa/resource_user_group.go b/cloudconnexa/resource_user_group.go index 8a7ff66..786160f 100644 --- a/cloudconnexa/resource_user_group.go +++ b/cloudconnexa/resource_user_group.go @@ -61,13 +61,18 @@ func resourceUserGroup() *schema.Resource { }, "vpn_region_ids": { Type: schema.TypeList, - Required: true, - MinItems: 1, - Description: "A list of VPN regions that are accessible to the user group.", + Optional: true, + Description: "A list of regions that are accessible to the user group.", Elem: &schema.Schema{ Type: schema.TypeString, }, }, + "all_regions_included": { + Type: schema.TypeBool, + Optional: true, + ExactlyOneOf: []string{"vpn_region_ids", "all_regions_included"}, + Description: "If true all regions will be available for this user group.", + }, }, } } @@ -106,14 +111,16 @@ func resourceDataToUserGroup(data *schema.ResourceData) *cloudconnexa.UserGroup for _, r := range configVpnRegionIds { vpnRegionIds = append(vpnRegionIds, r.(string)) } + allRegionsIncluded := data.Get("all_regions_included").(bool) ug := &cloudconnexa.UserGroup{ - Name: name, - ConnectAuth: connectAuth, - MaxDevice: maxDevice, - SystemSubnets: systemSubnets, - VpnRegionIds: vpnRegionIds, - InternetAccess: internetAccess, + Name: name, + ConnectAuth: connectAuth, + MaxDevice: maxDevice, + SystemSubnets: systemSubnets, + VpnRegionIds: vpnRegionIds, + InternetAccess: internetAccess, + AllRegionsIncluded: allRegionsIncluded, } return ug } @@ -124,8 +131,11 @@ func updateUserGroupData(data *schema.ResourceData, userGroup *cloudconnexa.User _ = data.Set("max_device", userGroup.MaxDevice) _ = data.Set("name", userGroup.Name) _ = data.Set("system_subnets", userGroup.SystemSubnets) - _ = data.Set("vpn_region_ids", userGroup.VpnRegionIds) _ = data.Set("internet_access", userGroup.InternetAccess) + if !userGroup.AllRegionsIncluded { + _ = data.Set("vpn_region_ids", userGroup.VpnRegionIds) + } + _ = data.Set("all_regions_included", userGroup.AllRegionsIncluded) } func resourceUserGroupDelete(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics { diff --git a/docs/data-sources/user_group.md b/docs/data-sources/user_group.md index 1a381f9..5f9cdfa 100644 --- a/docs/data-sources/user_group.md +++ b/docs/data-sources/user_group.md @@ -26,4 +26,5 @@ Use an `cloudconnexa_user_group` data source to read an CloudConnexa user group. - `internet_access` (String) The type of internet access provided. Valid values are `BLOCKED`, `GLOBAL_INTERNET`, or `LOCAL`. Defaults to `LOCAL`. - `max_device` (Number) The maximum number of devices per user. - `system_subnets` (List of String) The IPV4 and IPV6 addresses of the subnets associated with this user group. -- `vpn_region_ids` (List of String) The list of VPN region IDs this user group is associated with. +- `vpn_region_ids` (List of String) The list of region IDs this user group is associated with. +- `all_regions_included` (Boolean) If true all regions will be available for this user group. diff --git a/docs/resources/user_group.md b/docs/resources/user_group.md index b59b7e3..9eb5d45 100644 --- a/docs/resources/user_group.md +++ b/docs/resources/user_group.md @@ -18,7 +18,6 @@ Use `cloudconnexa_user_group` to create an CloudConnexa user group. ### Required - `name` (String) The name of the user group. -- `vpn_region_ids` (List of String) A list of VPN regions that are accessible to the user group. ### Optional @@ -26,6 +25,8 @@ Use `cloudconnexa_user_group` to create an CloudConnexa user group. - `internet_access` (String) - `max_device` (Number) The maximum number of devices that can be connected to the user group. - `system_subnets` (List of String) A list of subnets that are accessible to the user group. +- `vpn_region_ids` (List of String) A list of regions that are accessible to the user group. +- `all_regions_included` (Boolean) If true all regions will be available for this user group. ### Read-Only diff --git a/go.mod b/go.mod index 036d6c8..d276c49 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gruntwork-io/terratest v0.47.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 - github.com/openvpn/cloudconnexa-go-client/v2 v2.0.13 + github.com/openvpn/cloudconnexa-go-client/v2 v2.0.15 github.com/stretchr/testify v1.9.0 ) @@ -89,7 +89,7 @@ require ( golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.20.0 // indirect google.golang.org/api v0.162.0 // indirect google.golang.org/appengine v1.6.8 // indirect diff --git a/go.sum b/go.sum index bb2908a..eb55bc0 100644 --- a/go.sum +++ b/go.sum @@ -485,8 +485,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.13 h1:Bm47oT/O+CwXdwUu84NZZXETZCo/9Th3Cx+EGUXvyPU= -github.com/openvpn/cloudconnexa-go-client/v2 v2.0.13/go.mod h1:udq5IDkgXvMO6mQUEFsLHzEyGGAduhO0jJvlb9f4JkE= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.15 h1:AcU6zhs8WvOPQ7s3kJ+6ikk6RsJzKhgjTrMFnkIezdo= +github.com/openvpn/cloudconnexa-go-client/v2 v2.0.15/go.mod h1:WJZU+oOwHUYoO7Q2tFnGavKGbhrAvo8OEgvvr9EEtCw= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -797,8 +797,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From ff923229ed13f79dd9b22f387e234c81c1b92f34 Mon Sep 17 00:00:00 2001 From: Olexandr Lytvyn Date: Thu, 29 Aug 2024 14:15:27 +0300 Subject: [PATCH 20/20] Update examples and add README to examples --- example/README.md | 9 +++++++++ example/user_groups.tf | 11 +++++++++++ example/variables.tf | 17 ++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 example/README.md diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..685fe0b --- /dev/null +++ b/example/README.md @@ -0,0 +1,9 @@ +# Important +As for now currently examples inside this folder are just to show how some specific resources could look like, or how they could be implemented. +Examples inside this folder are not intended to provide complete picture or full working example. +Please be careful to understand what resources you copy from this folder and give it a double check if it will suite your needs (or not) and adjust this code to your specific needs. + +## Some generic consideration +If you have small amount of users it is okay to use local users (created inside CloudConnexa), examples in this folder will help you to achieve this. +If you have quite big amount of users - at some point it would be beneficial to look into managing users via LDAP or SAML. It is not possible (yet) configure LDAP and SAML settings via Terraform provider, this functionality will be added in the future releases. +If you have configured LDAP or SAML via CloudConnexa Admin UI - then using Terraform resource "cloudconnexa_user" will be not needed. diff --git a/example/user_groups.tf b/example/user_groups.tf index ce8e587..0afc045 100644 --- a/example/user_groups.tf +++ b/example/user_groups.tf @@ -1,5 +1,16 @@ +# Simple example resource "cloudconnexa_user_group" "this" { name = "test-group" vpn_region_ids = ["eu-central-1"] connect_auth = "AUTH" } + +# Advanced example +resource "cloudconnexa_user_group" "this" { + for_each = var.user_groups + name = each.key + connect_auth = try(each.value.connect_auth, "AUTO") + internet_access = try(each.value.internet_access, "LOCAL") + max_device = try(each.value.max_device, 3) + all_regions_included = true +} diff --git a/example/variables.tf b/example/variables.tf index 95bdead..2da1532 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -26,7 +26,7 @@ variable "users" { group = "Developer" role = "MEMBER" } - "Username3" = { + "Max_Mustermann" = { username = "Username3" email = "username3@company.com" group = "Support" @@ -68,3 +68,18 @@ variable "routes" { }, ] } + +variable "user_groups" { + description = "Variable for specifying configuration for User Groups" + type = map(object({ + connect_auth = optional(string) + internet_access = optional(string) + max_device = optional(number) + })) + default = { + admins = { max_device = 10 } + users = { max_device = 6 } + support = {} + marketing = {} + } +}