From 888eeb06fe138d4e11773ffc76a320e46e1b9326 Mon Sep 17 00:00:00 2001 From: Nicholas Wiersma Date: Thu, 1 Feb 2024 13:51:25 +0200 Subject: [PATCH] feat: support multiple instances (#16) --- docs/data-sources/armada_armada.md | 1 + docs/data-sources/armada_armada_v1.md | 1 + docs/data-sources/armada_armadaset.md | 1 + docs/data-sources/armada_armadaset_v1.md | 1 + docs/data-sources/container_branch.md | 1 + docs/data-sources/container_branch_v1.md | 1 + docs/data-sources/core_environment.md | 1 + docs/data-sources/core_environment_v1.md | 1 + docs/data-sources/core_region.md | 1 + docs/data-sources/core_region_v1.md | 1 + docs/data-sources/core_site.md | 1 + docs/data-sources/core_site_v1.md | 1 + docs/index.md | 42 +++- docs/resources/armada_armada.md | 1 + docs/resources/armada_armada_v1.md | 1 + docs/resources/armada_armadaset.md | 1 + docs/resources/armada_armadaset_v1.md | 1 + docs/resources/container_branch.md | 1 + docs/resources/container_branch_v1.md | 1 + docs/resources/core_environment.md | 1 + docs/resources/core_environment_v1.md | 1 + docs/resources/core_region.md | 1 + docs/resources/core_region_v1.md | 1 + docs/resources/core_site.md | 1 + docs/resources/core_site_v1.md | 1 + ec/armada/resource_armada.go | 12 +- ec/armada/resource_armadaset.go | 12 +- ec/armada/schema_armada.go | 5 + ec/armada/schema_armadaset.go | 5 + ec/container/resource_branch.go | 12 +- ec/container/schema_branch.go | 5 + ec/core/resource_core_environment.go | 12 +- ec/core/resource_core_region.go | 12 +- ec/core/resource_core_site.go | 12 +- ec/core/resource_core_site_test.go | 17 +- ec/core/schema_environment.go | 5 + ec/core/schema_region.go | 5 + ec/core/schema_site.go | 5 + ec/ec.go | 38 +++- ec/provider/provider.go | 214 ++++++++++++++---- ec/provider/providertest/provider.go | 5 +- examples/provider/provider.tf | 23 +- internal/cmd/schema-gen/gen.go | 46 ++-- .../schema-gen/testdata/schema_testobject.go | 5 + 44 files changed, 418 insertions(+), 98 deletions(-) diff --git a/docs/data-sources/armada_armada.md b/docs/data-sources/armada_armada.md index 0b5a743..4f86ed7 100644 --- a/docs/data-sources/armada_armada.md +++ b/docs/data-sources/armada_armada.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Armada. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armada. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/armada_armada_v1.md b/docs/data-sources/armada_armada_v1.md index c89c8fd..7b68039 100644 --- a/docs/data-sources/armada_armada_v1.md +++ b/docs/data-sources/armada_armada_v1.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Armada. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armada. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/armada_armadaset.md b/docs/data-sources/armada_armadaset.md index c897747..8b70090 100644 --- a/docs/data-sources/armada_armadaset.md +++ b/docs/data-sources/armada_armadaset.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing ArmadaSet. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armadas in this set. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/armada_armadaset_v1.md b/docs/data-sources/armada_armadaset_v1.md index 3c395a7..53f5f2f 100644 --- a/docs/data-sources/armada_armadaset_v1.md +++ b/docs/data-sources/armada_armadaset_v1.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing ArmadaSet. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armadas in this set. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/container_branch.md b/docs/data-sources/container_branch.md index abe6a9c..5eb2be4 100644 --- a/docs/data-sources/container_branch.md +++ b/docs/data-sources/container_branch.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Branch. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired branch. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/container_branch_v1.md b/docs/data-sources/container_branch_v1.md index 7886680..378293d 100644 --- a/docs/data-sources/container_branch_v1.md +++ b/docs/data-sources/container_branch_v1.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Branch. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired branch. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/core_environment.md b/docs/data-sources/core_environment.md index a5c117c..e86f770 100644 --- a/docs/data-sources/core_environment.md +++ b/docs/data-sources/core_environment.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Environment. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec configures the environment. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/core_environment_v1.md b/docs/data-sources/core_environment_v1.md index 4cc2062..6d15f7e 100644 --- a/docs/data-sources/core_environment_v1.md +++ b/docs/data-sources/core_environment_v1.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Environment. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec configures the environment. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/core_region.md b/docs/data-sources/core_region.md index 2fc79a0..f2c4e73 100644 --- a/docs/data-sources/core_region.md +++ b/docs/data-sources/core_region.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Region. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired region configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/core_region_v1.md b/docs/data-sources/core_region_v1.md index 73ec2d5..a09683e 100644 --- a/docs/data-sources/core_region_v1.md +++ b/docs/data-sources/core_region_v1.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Region. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired region configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/core_site.md b/docs/data-sources/core_site.md index e66b5a7..283e508 100644 --- a/docs/data-sources/core_site.md +++ b/docs/data-sources/core_site.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Site. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired site configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/data-sources/core_site_v1.md b/docs/data-sources/core_site_v1.md index 0f8236b..cc425c5 100644 --- a/docs/data-sources/core_site_v1.md +++ b/docs/data-sources/core_site_v1.md @@ -17,6 +17,7 @@ Use this data source to access information about an existing Site. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired site configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/index.md b/docs/index.md index 37f175e..19ce625 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,7 +23,11 @@ terraform { } provider "ec" { - host = "" + host = "" + instances { + name = "my-other-instance" + host = "" + } } resource "ec_core_site" "test" { @@ -41,6 +45,23 @@ resource "ec_core_site" "test" { } } } + +resource "ec_core_site" "test2" { + instance = "my-other-instance" + metadata { + name = "test" + } + + spec { + description = "My other test" + credentials { + endpoint = "" + certificate = "" + namespace = "" + token = "" + } + } +} ``` @@ -50,7 +71,24 @@ resource "ec_core_site" "test" { - `client_id` (String) The oAuth2 client id to authenticate against. - `client_secret` (String) The oAuth2 client secret to authenticate against. -- `host` (String) The hostname (in form of URI) of Armada API. +- `host` (String) The hostname (in form of URI) of the Enterprise Console API. +- `instances` (Block List) Named Enterprise Console instances. (see [below for nested schema](#nestedblock--instances)) +- `password` (String) The password to authenticate with. +- `token_endpoint` (String) The URI to the token authentication endpoint. +- `username` (String) The user to authenticate with. + + +### Nested Schema for `instances` + +Required: + +- `client_id` (String) The oAuth2 client id to authenticate against. +- `host` (String) The hostname (in form of URI) of the Enterprise Console API. +- `name` (String) The instance name. + +Optional: + +- `client_secret` (String) The oAuth2 client secret to authenticate against. - `password` (String) The password to authenticate with. - `token_endpoint` (String) The URI to the token authentication endpoint. - `username` (String) The user to authenticate with. diff --git a/docs/resources/armada_armada.md b/docs/resources/armada_armada.md index d900752..83fbabd 100644 --- a/docs/resources/armada_armada.md +++ b/docs/resources/armada_armada.md @@ -17,6 +17,7 @@ An Armada distributes a specified number of Game Servers across a Region. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armada. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/armada_armada_v1.md b/docs/resources/armada_armada_v1.md index 9b06387..2cd3699 100644 --- a/docs/resources/armada_armada_v1.md +++ b/docs/resources/armada_armada_v1.md @@ -17,6 +17,7 @@ An Armada distributes a specified number of Game Servers across a Region. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armada. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/armada_armadaset.md b/docs/resources/armada_armadaset.md index c82f94d..732119c 100644 --- a/docs/resources/armada_armadaset.md +++ b/docs/resources/armada_armadaset.md @@ -17,6 +17,7 @@ An ArmadaSet manages Armadas across multiple Regions, while sharing a common spe ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armadas in this set. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/armada_armadaset_v1.md b/docs/resources/armada_armadaset_v1.md index e79618d..03e51df 100644 --- a/docs/resources/armada_armadaset_v1.md +++ b/docs/resources/armada_armadaset_v1.md @@ -17,6 +17,7 @@ An ArmadaSet manages Armadas across multiple Regions, while sharing a common spe ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired armadas in this set. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/container_branch.md b/docs/resources/container_branch.md index a64be7e..fcbc3e4 100644 --- a/docs/resources/container_branch.md +++ b/docs/resources/container_branch.md @@ -30,6 +30,7 @@ resource "ec_container_branch" "test" { ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired branch. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/container_branch_v1.md b/docs/resources/container_branch_v1.md index 75e3c7e..6634e81 100644 --- a/docs/resources/container_branch_v1.md +++ b/docs/resources/container_branch_v1.md @@ -30,6 +30,7 @@ resource "ec_container_branch_v1" "test" { ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired branch. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/core_environment.md b/docs/resources/core_environment.md index c17e43e..dd2231a 100644 --- a/docs/resources/core_environment.md +++ b/docs/resources/core_environment.md @@ -17,6 +17,7 @@ An Environment provides a mechanism to isolate groups of resources. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec configures the environment. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/core_environment_v1.md b/docs/resources/core_environment_v1.md index 4816fb6..d249a82 100644 --- a/docs/resources/core_environment_v1.md +++ b/docs/resources/core_environment_v1.md @@ -17,6 +17,7 @@ An Environment provides a mechanism to isolate groups of resources. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec configures the environment. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/core_region.md b/docs/resources/core_region.md index 26dcfeb..aa93ec7 100644 --- a/docs/resources/core_region.md +++ b/docs/resources/core_region.md @@ -17,6 +17,7 @@ A Region determines how Armadas are distributed across Sites. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired region configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/core_region_v1.md b/docs/resources/core_region_v1.md index 2ca7c3c..adc1261 100644 --- a/docs/resources/core_region_v1.md +++ b/docs/resources/core_region_v1.md @@ -17,6 +17,7 @@ A Region determines how Armadas are distributed across Sites. ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired region configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/core_site.md b/docs/resources/core_site.md index 8b436d1..1503e67 100644 --- a/docs/resources/core_site.md +++ b/docs/resources/core_site.md @@ -35,6 +35,7 @@ resource "ec_core_site" "test" { ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired site configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/docs/resources/core_site_v1.md b/docs/resources/core_site_v1.md index 2d628b5..caea674 100644 --- a/docs/resources/core_site_v1.md +++ b/docs/resources/core_site_v1.md @@ -35,6 +35,7 @@ resource "ec_core_site" "test" { ### Optional +- `instance` (String) Name is an instance name configured in the provider. - `metadata` (Block List, Max: 1) Standard object's metadata. (see [below for nested schema](#nestedblock--metadata)) - `spec` (Block List, Max: 1) Spec defines the desired site configuration. (see [below for nested schema](#nestedblock--spec)) diff --git a/ec/armada/resource_armada.go b/ec/armada/resource_armada.go index 0e0e26b..eba75ec 100644 --- a/ec/armada/resource_armada.go +++ b/ec/armada/resource_armada.go @@ -28,7 +28,8 @@ func ResourceArmada() *schema.Resource { } func resourceArmadaRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -58,7 +59,8 @@ func resourceArmadaRead(ctx context.Context, d *schema.ResourceData, m any) diag } func resourceArmadaCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -83,7 +85,8 @@ func resourceArmadaCreate(ctx context.Context, d *schema.ResourceData, m any) di } func resourceArmadaUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -108,7 +111,8 @@ func resourceArmadaUpdate(ctx context.Context, d *schema.ResourceData, m any) di } func resourceArmadaDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } diff --git a/ec/armada/resource_armadaset.go b/ec/armada/resource_armadaset.go index 3cf9de6..378a976 100644 --- a/ec/armada/resource_armadaset.go +++ b/ec/armada/resource_armadaset.go @@ -28,7 +28,8 @@ func ResourceArmadaSet() *schema.Resource { } func resourceArmadaSetRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -58,7 +59,8 @@ func resourceArmadaSetRead(ctx context.Context, d *schema.ResourceData, m any) d } func resourceArmadaSetCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -83,7 +85,8 @@ func resourceArmadaSetCreate(ctx context.Context, d *schema.ResourceData, m any) } func resourceArmadaSetUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -108,7 +111,8 @@ func resourceArmadaSetUpdate(ctx context.Context, d *schema.ResourceData, m any) } func resourceArmadaSetDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } diff --git a/ec/armada/schema_armada.go b/ec/armada/schema_armada.go index 09e5d69..3857571 100644 --- a/ec/armada/schema_armada.go +++ b/ec/armada/schema_armada.go @@ -9,6 +9,11 @@ import ( func armadaSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, "metadata": { Type: schema.TypeList, Description: "Standard object's metadata.", diff --git a/ec/armada/schema_armadaset.go b/ec/armada/schema_armadaset.go index d5d2bc4..0735f39 100644 --- a/ec/armada/schema_armadaset.go +++ b/ec/armada/schema_armadaset.go @@ -9,6 +9,11 @@ import ( func armadaSetSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, "metadata": { Type: schema.TypeList, Description: "Standard object's metadata.", diff --git a/ec/container/resource_branch.go b/ec/container/resource_branch.go index ee74574..1a16ee7 100644 --- a/ec/container/resource_branch.go +++ b/ec/container/resource_branch.go @@ -28,7 +28,8 @@ func ResourceBranch() *schema.Resource { } func resourceBranchRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -58,7 +59,8 @@ func resourceBranchRead(ctx context.Context, d *schema.ResourceData, m any) diag } func resourceBranchCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -83,7 +85,8 @@ func resourceBranchCreate(ctx context.Context, d *schema.ResourceData, m any) di } func resourceBranchUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -108,7 +111,8 @@ func resourceBranchUpdate(ctx context.Context, d *schema.ResourceData, m any) di } func resourceBranchDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } diff --git a/ec/container/schema_branch.go b/ec/container/schema_branch.go index ed0c062..7c1a5d7 100644 --- a/ec/container/schema_branch.go +++ b/ec/container/schema_branch.go @@ -9,6 +9,11 @@ import ( func branchSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, "metadata": { Type: schema.TypeList, Description: "Standard object's metadata.", diff --git a/ec/core/resource_core_environment.go b/ec/core/resource_core_environment.go index dfd3d27..3609c05 100644 --- a/ec/core/resource_core_environment.go +++ b/ec/core/resource_core_environment.go @@ -28,7 +28,8 @@ func ResourceEnvironment() *schema.Resource { } func resourceEnvironmentRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -58,7 +59,8 @@ func resourceEnvironmentRead(ctx context.Context, d *schema.ResourceData, m any) } func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -81,7 +83,8 @@ func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, m an } func resourceEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -104,7 +107,8 @@ func resourceEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, m an } func resourceEnvironmentDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } diff --git a/ec/core/resource_core_region.go b/ec/core/resource_core_region.go index 617d223..fbdc7e2 100644 --- a/ec/core/resource_core_region.go +++ b/ec/core/resource_core_region.go @@ -28,7 +28,8 @@ func ResourceRegion() *schema.Resource { } func resourceRegionRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -58,7 +59,8 @@ func resourceRegionRead(ctx context.Context, d *schema.ResourceData, m any) diag } func resourceRegionCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -83,7 +85,8 @@ func resourceRegionCreate(ctx context.Context, d *schema.ResourceData, m any) di } func resourceRegionUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -108,7 +111,8 @@ func resourceRegionUpdate(ctx context.Context, d *schema.ResourceData, m any) di } func resourceRegionDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } diff --git a/ec/core/resource_core_site.go b/ec/core/resource_core_site.go index c50d99c..2a7926e 100644 --- a/ec/core/resource_core_site.go +++ b/ec/core/resource_core_site.go @@ -28,7 +28,8 @@ func ResourceSite() *schema.Resource { } func resourceSiteRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -58,7 +59,8 @@ func resourceSiteRead(ctx context.Context, d *schema.ResourceData, m any) diag.D } func resourceSiteCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -83,7 +85,8 @@ func resourceSiteCreate(ctx context.Context, d *schema.ResourceData, m any) diag } func resourceSiteUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } @@ -108,7 +111,8 @@ func resourceSiteUpdate(ctx context.Context, d *schema.ResourceData, m any) diag } func resourceSiteDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - clientSet, err := ec.ResolveClientSet(m) + inst, _ := d.Get("instance").(string) + clientSet, err := ec.ResolveClientSet(m, inst) if err != nil { return diag.FromErr(err) } diff --git a/ec/core/resource_core_site_test.go b/ec/core/resource_core_site_test.go index 4494c7c..7d10af5 100644 --- a/ec/core/resource_core_site_test.go +++ b/ec/core/resource_core_site_test.go @@ -24,6 +24,7 @@ func TestResourceSites(t *testing.T) { { Config: testResourceSitesConfigBasic(name), Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ec_core_site.test", "instance", "test"), resource.TestCheckResourceAttr("ec_core_site.test", "metadata.0.name", name), resource.TestCheckResourceAttr("ec_core_site.test", "spec.#", "1"), resource.TestCheckResourceAttr("ec_core_site.test", "spec.0.description", "My Site"), @@ -38,6 +39,7 @@ func TestResourceSites(t *testing.T) { { Config: testResourceSitesConfigBasic2(name), Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ec_core_site.test", "instance", "test"), resource.TestCheckResourceAttr("ec_core_site.test", "metadata.0.name", name), resource.TestCheckResourceAttr("ec_core_site.test", "metadata.0.labels.foo", "bar"), resource.TestCheckResourceAttr("ec_core_site.test", "spec.#", "1"), @@ -53,6 +55,7 @@ func TestResourceSites(t *testing.T) { { Config: testResourceSitesConfigBasicWithEnv(name), Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("ec_core_site.test", "instance", "test"), resource.TestCheckResourceAttr("ec_core_site.test", "metadata.0.name", name), resource.TestCheckResourceAttr("ec_core_site.test", "spec.#", "1"), resource.TestCheckResourceAttr("ec_core_site.test", "spec.0.description", "My Other Site"), @@ -72,9 +75,10 @@ func TestResourceSites(t *testing.T) { ), }, { - ResourceName: "ec_core_site.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "ec_core_site.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"instance"}, }, }, }) @@ -82,6 +86,7 @@ func TestResourceSites(t *testing.T) { func testResourceSitesConfigBasic(name string) string { return fmt.Sprintf(`resource "ec_core_site" "test" { + instance = "test" metadata { name = "%s" } @@ -103,6 +108,7 @@ func testResourceSitesConfigBasic(name string) string { func testResourceSitesConfigBasic2(name string) string { return fmt.Sprintf(`resource "ec_core_site" "test" { + instance = "test" metadata { name = "%s" labels = { @@ -127,6 +133,7 @@ func testResourceSitesConfigBasic2(name string) string { func testResourceSitesConfigBasicWithEnv(name string) string { return fmt.Sprintf(`resource "ec_core_site" "test" { + instance = "test" metadata { name = "%s" } @@ -168,7 +175,7 @@ func testResourceSitesConfigBasicWithEnv(name string) string { func testCheckSiteDestroy(cs clientset.Interface) func(s *terraform.State) error { return func(s *terraform.State) error { for _, rs := range s.RootModule().Resources { - if rs.Type != "ec_armada_site" { + if rs.Type != "ec_core_site" { continue } @@ -176,7 +183,7 @@ func testCheckSiteDestroy(cs clientset.Interface) func(s *terraform.State) error resp, err := cs.CoreV1().Sites().Get(context.Background(), name, metav1.GetOptions{}) if err == nil { if resp.Name == rs.Primary.ID { - return fmt.Errorf("Site still exists: %s", rs.Primary.ID) + return fmt.Errorf("site still exists: %s", rs.Primary.ID) } } } diff --git a/ec/core/schema_environment.go b/ec/core/schema_environment.go index 8360b85..7760665 100644 --- a/ec/core/schema_environment.go +++ b/ec/core/schema_environment.go @@ -9,6 +9,11 @@ import ( func environmentSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, "metadata": { Type: schema.TypeList, Description: "Standard object's metadata.", diff --git a/ec/core/schema_region.go b/ec/core/schema_region.go index 990d026..edb29f1 100644 --- a/ec/core/schema_region.go +++ b/ec/core/schema_region.go @@ -9,6 +9,11 @@ import ( func regionSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, "metadata": { Type: schema.TypeList, Description: "Standard object's metadata.", diff --git a/ec/core/schema_site.go b/ec/core/schema_site.go index 5431efd..14197ec 100644 --- a/ec/core/schema_site.go +++ b/ec/core/schema_site.go @@ -9,6 +9,11 @@ import ( func siteSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, "metadata": { Type: schema.TypeList, Description: "Standard object's metadata.", diff --git a/ec/ec.go b/ec/ec.go index 5133566..0efa19c 100644 --- a/ec/ec.go +++ b/ec/ec.go @@ -2,6 +2,7 @@ package ec import ( "errors" + "fmt" "strings" "github.com/nitrado/tfconv" @@ -9,13 +10,42 @@ import ( "k8s.io/apimachinery/pkg/api/resource" ) +// ProviderContext contains connection context information. +type ProviderContext struct { + defaultCS clientset.Interface + instances map[string]clientset.Interface +} + +// NewProviderContext returns a provider context with the given default clientset and instances. +func NewProviderContext(defCS clientset.Interface, instances map[string]clientset.Interface) ProviderContext { + if instances == nil { + instances = map[string]clientset.Interface{} + } + return ProviderContext{ + defaultCS: defCS, + instances: instances, + } +} + // ResolveClientSet resolves the ClientSet from the given context. -func ResolveClientSet(m any) (clientset.Interface, error) { - clientSet, ok := m.(clientset.Interface) +func ResolveClientSet(m any, name string) (clientset.Interface, error) { + connCtx, ok := m.(ProviderContext) if !ok { - return nil, errors.New("invalid clientset") + return nil, errors.New("invalid connection context") + } + + if name == "" { + if connCtx.defaultCS == nil { + return nil, errors.New("no default clientset found") + } + return connCtx.defaultCS, nil + } + + cs, ok := connCtx.instances[name] + if !ok || cs == nil { + return nil, fmt.Errorf("instance %q clientset not found", name) } - return clientSet, nil + return cs, nil } // ScopedName returns the encoded name of an object. diff --git a/ec/provider/provider.go b/ec/provider/provider.go index 343dc43..bb62256 100644 --- a/ec/provider/provider.go +++ b/ec/provider/provider.go @@ -2,11 +2,13 @@ package provider import ( "context" + "errors" "fmt" "net/url" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/nitrado/terraform-provider-ec/ec" "github.com/nitrado/terraform-provider-ec/ec/armada" "github.com/nitrado/terraform-provider-ec/ec/container" "github.com/nitrado/terraform-provider-ec/ec/core" @@ -22,40 +24,84 @@ func Provider() *schema.Provider { Schema: map[string]*schema.Schema{ "host": { Type: schema.TypeString, - Required: true, - DefaultFunc: schema.EnvDefaultFunc("ARMADA_HOST", ""), - Description: "The hostname (in form of URI) of Armada API.", + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("EC_HOST", ""), + Description: "The hostname (in form of URI) of the Enterprise Console API.", }, "token_endpoint": { Type: schema.TypeString, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("ARMADA_TOKEN_ENDPOINT", ""), + DefaultFunc: schema.EnvDefaultFunc("EC_TOKEN_ENDPOINT", ""), Description: "The URI to the token authentication endpoint.", }, "client_id": { Type: schema.TypeString, - Required: true, - DefaultFunc: schema.EnvDefaultFunc("ARMADA_CLIENT_ID", ""), + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("EC_CLIENT_ID", ""), Description: "The oAuth2 client id to authenticate against.", }, "client_secret": { Type: schema.TypeString, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("ARMADA_CLIENT_SECRET", ""), + DefaultFunc: schema.EnvDefaultFunc("EC_CLIENT_SECRET", ""), Description: "The oAuth2 client secret to authenticate against.", }, "username": { Type: schema.TypeString, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("ARMADA_USERNAME", ""), + DefaultFunc: schema.EnvDefaultFunc("EC_USERNAME", ""), Description: "The user to authenticate with.", }, "password": { Type: schema.TypeString, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("ARMADA_PASSWORD", ""), + DefaultFunc: schema.EnvDefaultFunc("EC_PASSWORD", ""), Description: "The password to authenticate with.", }, + "instances": { + Type: schema.TypeList, + Optional: true, + Description: "Named Enterprise Console instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "The instance name.", + }, + "host": { + Type: schema.TypeString, + Required: true, + Description: "The hostname (in form of URI) of the Enterprise Console API.", + }, + "token_endpoint": { + Type: schema.TypeString, + Optional: true, + Description: "The URI to the token authentication endpoint.", + }, + "client_id": { + Type: schema.TypeString, + Required: true, + Description: "The oAuth2 client id to authenticate against.", + }, + "client_secret": { + Type: schema.TypeString, + Optional: true, + Description: "The oAuth2 client secret to authenticate against.", + }, + "username": { + Type: schema.TypeString, + Optional: true, + Description: "The user to authenticate with.", + }, + "password": { + Type: schema.TypeString, + Optional: true, + Description: "The password to authenticate with.", + }, + }, + }, + }, }, DataSourcesMap: map[string]*schema.Resource{ "ec_armada_armada": armada.DataSourceArmada(), @@ -95,77 +141,129 @@ func Provider() *schema.Provider { } func providerConfigure(_ context.Context, d *schema.ResourceData, _ string) (any, diag.Diagnostics) { - //nolint:contextcheck - tok, err := resolveToken(d) - if err != nil { - return nil, diag.FromErr(err) + var defaultClientSet clientset.Interface + if v, ok := d.Get("host").(string); ok && v != "" { + var err error + defaultClientSet, err = createClientSet("", collectConnData(d)) //nolint:contextcheck + if err != nil { + return nil, diag.FromErr(err) + } + } + + var instances map[string]clientset.Interface + if insts, ok := d.Get("instances").([]any); ok { + instances = make(map[string]clientset.Interface, len(insts)) + for _, v := range insts { + inst := v.(map[string]any) + + name := inst["name"].(string) + cs, err := createClientSet(name, inst) //nolint:contextcheck + if err != nil { + return nil, diag.FromErr(err) + } + instances[name] = cs + } } - if _, err = tok.Token(); err != nil { - return nil, diag.FromErr(err) + + if defaultClientSet == nil && len(instances) == 0 { + return nil, diag.FromErr(errors.New("at least one instance or default connection details must be provided")) } + return ec.NewProviderContext(defaultClientSet, instances), nil +} - cfg := createRESTConfig(d) - cfg.BearerTokenSource = tok +func collectConnData(d *schema.ResourceData) map[string]any { + return map[string]any{ + "host": d.Get("host"), + "token_endpoint": d.Get("token_endpoint"), + "client_id": d.Get("client_id"), + "client_secret": d.Get("client_secret"), + "username": d.Get("username"), + "password": d.Get("password"), + } +} + +func createClientSet(name string, m map[string]any) (clientset.Interface, error) { + var forInstance string + if name != "" { + forInstance = `for instance "` + name + `"` + } + + tok, err := resolveToken(m) + if err != nil { + return nil, fmt.Errorf("retrieveing token %s: %w", forInstance, err) + } + cfg := createRESTConfig(m, tok) clientSet, err := clientset.New(cfg) if err != nil { - return nil, diag.FromErr(fmt.Errorf("could not to configure client: %w", err)) + return nil, fmt.Errorf("could not to configure client %s: %w", forInstance, err) } return clientSet, nil } -func createRESTConfig(d *schema.ResourceData) rest.Config { +func createRESTConfig(m map[string]any, tok oauth2.TokenSource) rest.Config { var cfg rest.Config - cfg.BaseURL = d.Get("host").(string) + cfg.BaseURL = m["host"].(string) + cfg.BearerTokenSource = tok return cfg } -func resolveToken(d *schema.ResourceData) (oauth2.TokenSource, error) { - tokURL, err := resolveTokenURL(d) +func resolveToken(m map[string]any) (oauth2.TokenSource, error) { + tokURL, err := resolveTokenURL(m) if err != nil { return nil, err } - clientID := d.Get("client_id").(string) - clientSecret, hasClientSecret := d.Get("client_secret").(string) - user, hasUser := d.Get("username").(string) - pass, hasPass := d.Get("password").(string) + clientID, ok := m["client_id"].(string) + if !ok { + return nil, fmt.Errorf("client id is required") + } + + clientSecret, hasClientSecret := m["client_secret"].(string) + user, hasUser := m["username"].(string) + pass, hasPass := m["password"].(string) switch { case hasUser && hasPass: - cfg := oauth2.Config{ - ClientID: clientID, - Endpoint: oauth2.Endpoint{ - TokenURL: tokURL, - AuthStyle: oauth2.AuthStyleInHeader, - }, - } - tok, err := cfg.PasswordCredentialsToken(context.Background(), user, pass) - if err != nil { - return nil, err - } - return cfg.TokenSource(context.Background(), tok), nil + return newLazyTokenSource(func() (oauth2.TokenSource, error) { + cfg := oauth2.Config{ + ClientID: clientID, + Scopes: []string{"openid", "email", "profile", "offline_access"}, + Endpoint: oauth2.Endpoint{ + AuthStyle: oauth2.AuthStyleInHeader, + TokenURL: tokURL, + }, + } + tok, err := cfg.PasswordCredentialsToken(context.Background(), user, pass) + if err != nil { + return nil, err + } + return cfg.TokenSource(context.Background(), tok), nil + }), nil case hasClientSecret: - cfg := clientcredentials.Config{ - ClientID: clientID, - ClientSecret: clientSecret, - TokenURL: tokURL, - AuthStyle: oauth2.AuthStyleInHeader, - } - return cfg.TokenSource(context.Background()), nil + return newLazyTokenSource(func() (oauth2.TokenSource, error) { + cfg := clientcredentials.Config{ + ClientID: clientID, + ClientSecret: clientSecret, + TokenURL: tokURL, + Scopes: []string{"openid", "email", "profile", "offline_access"}, + AuthStyle: oauth2.AuthStyleInHeader, + } + return cfg.TokenSource(context.Background()), nil + }), nil default: return nil, fmt.Errorf("either client_secret or username and password must be set") } } -func resolveTokenURL(d *schema.ResourceData) (string, error) { - if tokenEndpoint, ok := d.Get("token_endpoint").(string); ok && tokenEndpoint != "" { +func resolveTokenURL(m map[string]any) (string, error) { + if tokenEndpoint, ok := m["token_endpoint"].(string); ok && tokenEndpoint != "" { return tokenEndpoint, nil } - host := d.Get("host").(string) + host := m["host"].(string) u, err := url.Parse(host) if err != nil { return "", fmt.Errorf("invalid host: %w", err) @@ -174,3 +272,23 @@ func resolveTokenURL(d *schema.ResourceData) (string, error) { u.Path = "/auth/realms/enterprise-console/protocol/openid-connect/token" return u.String(), nil } + +type lazyTokenSource struct { + ts oauth2.TokenSource + newFn func() (oauth2.TokenSource, error) +} + +func newLazyTokenSource(newFn func() (oauth2.TokenSource, error)) *lazyTokenSource { + return &lazyTokenSource{newFn: newFn} +} + +func (s *lazyTokenSource) Token() (*oauth2.Token, error) { + if s.ts == nil { + var err error + s.ts, err = s.newFn() + if err != nil { + return nil, err + } + } + return s.ts.Token() +} diff --git a/ec/provider/providertest/provider.go b/ec/provider/providertest/provider.go index 99abcac..b4d23ed 100644 --- a/ec/provider/providertest/provider.go +++ b/ec/provider/providertest/provider.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/nitrado/terraform-provider-ec/ec" "github.com/nitrado/terraform-provider-ec/ec/provider" "github.com/stretchr/testify/require" "gitlab.com/nitrado/b2b/ec/apicore/runtime" @@ -25,7 +26,9 @@ func SetupProviderFactories(t *testing.T, objs ...runtime.Object) (map[string]fu "ec": func() (*schema.Provider, error) { p := provider.Provider() p.ConfigureContextFunc = func(context.Context, *schema.ResourceData) (any, diag.Diagnostics) { - return cs, nil + return ec.NewProviderContext(cs, map[string]clientset.Interface{ + "test": cs, + }), nil } return p, nil }, diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 72efdf6..e442435 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -9,7 +9,11 @@ terraform { } provider "ec" { - host = "" + host = "" + instances { + name = "my-other-instance" + host = "" + } } resource "ec_core_site" "test" { @@ -27,3 +31,20 @@ resource "ec_core_site" "test" { } } } + +resource "ec_core_site" "test2" { + instance = "my-other-instance" + metadata { + name = "test" + } + + spec { + description = "My other test" + credentials { + endpoint = "" + certificate = "" + namespace = "" + token = "" + } + } +} diff --git a/internal/cmd/schema-gen/gen.go b/internal/cmd/schema-gen/gen.go index 5faef79..b8c4969 100644 --- a/internal/cmd/schema-gen/gen.go +++ b/internal/cmd/schema-gen/gen.go @@ -39,24 +39,35 @@ func (g *Generator) Generate(obj any, pkgName, fnName string) ([]byte, error) { return nil, err } - var needsMeta bool + imports := make([]string, 0, 1) for _, s := range fields { - if strings.Contains(s, "meta.") { - needsMeta = true + if !strings.Contains(s, "meta.") { + continue } + imports = append(imports, "github.com/nitrado/terraform-provider-ec/ec/meta") + } + + var isAPIObj bool + for name := range fields { + if name != "metadata" { + continue + } + isAPIObj = true } buf := &bytes.Buffer{} err = fileTmpl.Execute(buf, struct { - PkgName string - FuncName string - Fields map[string]string - NeedsMeta bool + PkgName string + Imports []string + FuncName string + Fields map[string]string + IsAPIObj bool }{ - PkgName: pkgName, - FuncName: fnName, - Fields: fields, - NeedsMeta: needsMeta, + PkgName: pkgName, + Imports: imports, + FuncName: fnName, + Fields: fields, + IsAPIObj: isAPIObj, }) if err != nil { return nil, err @@ -136,10 +147,12 @@ var fileTmpl = template.Must(template.New("code").Parse(`package {{.PkgName}} // Code generated by schema-gen. DO NOT EDIT. -{{ if .NeedsMeta }} +{{ if .Imports }} import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/nitrado/terraform-provider-ec/ec/meta" +{{- range $import := .Imports }} + "{{ $import }}" +{{- end }} ) {{- else }} import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -147,6 +160,13 @@ import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" func {{.FuncName}}() map[string]*schema.Schema { return map[string]*schema.Schema{ +{{- if .IsAPIObj }} + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, +{{- end }} {{- range $name, $schema := .Fields }} "{{ $name }}": {{ $schema }}, {{- end }} diff --git a/internal/cmd/schema-gen/testdata/schema_testobject.go b/internal/cmd/schema-gen/testdata/schema_testobject.go index c0cb9c8..bd8a039 100644 --- a/internal/cmd/schema-gen/testdata/schema_testobject.go +++ b/internal/cmd/schema-gen/testdata/schema_testobject.go @@ -9,6 +9,11 @@ import ( func testObjectSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ + "instance": { + Type: schema.TypeString, + Description: "Name is an instance name configured in the provider.", + Optional: true, + }, "bool": { Type: schema.TypeBool, Required: true,