diff --git a/docs/resources/workspace.md b/docs/resources/workspace.md new file mode 100644 index 0000000..d8be144 --- /dev/null +++ b/docs/resources/workspace.md @@ -0,0 +1,21 @@ +# kong_workspace + +## Example Usage + +```hcl +resource "kong_workspace" "workspace" { + name = "myworkspace" +} +``` + +## Argument Reference + +* `name` - (Required) The name of the Kong workspace. + +## Import + +Import workspaces using the workspace id: + +```shell +terraform import kong_workspace. +``` diff --git a/kong/provider.go b/kong/provider.go index 0dcc2f9..e6ade48 100644 --- a/kong/provider.go +++ b/kong/provider.go @@ -79,6 +79,7 @@ func Provider() *schema.Provider { "kong_service": resourceKongService(), "kong_route": resourceKongRoute(), "kong_consumer_jwt_auth": resourceKongConsumerJWTAuth(), + "kong_workspace": resourceKongWorkspace(), }, //DataSourcesMap: map[string]*schema.Resource{ diff --git a/kong/provider_test.go b/kong/provider_test.go index aa403a4..a098eee 100644 --- a/kong/provider_test.go +++ b/kong/provider_test.go @@ -69,7 +69,7 @@ func TestProvider_configure_strict(t *testing.T) { func TestMain(m *testing.M) { - testContext := containers.StartKong(defaultKongRepository, GetEnvVarOrDefault("KONG_VERSION", defaultKongVersion), defaultKongLicense) + testContext := containers.StartKong(defaultKongRepository, GetEnvVarOrDefault("KONG_VERSION", defaultKongVersion), GetEnvVarOrDefault("KONG_LICENSE_DATA", defaultKongLicense)) err := os.Setenv(EnvKongAdminHostAddress, testContext.KongHostAddress) if err != nil { diff --git a/kong/resource_kong_workspace.go b/kong/resource_kong_workspace.go new file mode 100644 index 0000000..b5ace51 --- /dev/null +++ b/kong/resource_kong_workspace.go @@ -0,0 +1,91 @@ +package kong + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/kong/go-kong/kong" +) + +func resourceKongWorkspace() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceKongWorkspaceCreate, + ReadContext: resourceKongWorkspaceRead, + DeleteContext: resourceKongWorkspaceDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + }, + } +} + +func resourceKongWorkspaceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + + workspaceRequest := createKongWorkspaceRequestFromResourceData(d) + + client := meta.(*config).adminClient.Workspaces + workspace, err := client.Create(ctx, workspaceRequest) + if err != nil { + return diag.FromErr(fmt.Errorf("failed to create kong workspace: %v error: %v", workspaceRequest, err)) + } + + d.SetId(*workspace.ID) + + return resourceKongWorkspaceRead(ctx, d, meta) +} + +func resourceKongWorkspaceRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + client := meta.(*config).adminClient.Workspaces + workspace, err := client.Get(ctx, kong.String(d.Id())) + + if !kong.IsNotFoundErr(err) && err != nil { + return diag.FromErr(fmt.Errorf("could not find kong workspace: %v", err)) + } + + if workspace == nil { + d.SetId("") + } else { + if workspace.Name != nil { + err := d.Set("name", workspace.Name) + if err != nil { + return diag.FromErr(err) + } + } + } + + return diags +} + +func resourceKongWorkspaceDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + client := meta.(*config).adminClient.Workspaces + err := client.Delete(ctx, kong.String(d.Id())) + + if err != nil { + return diag.FromErr(fmt.Errorf("could not delete kong workspace: %v", err)) + } + + return diags +} + +func createKongWorkspaceRequestFromResourceData(d *schema.ResourceData) *kong.Workspace { + + workspace := &kong.Workspace{ + Name: readStringPtrFromResource(d, "name"), + } + if d.Id() != "" { + workspace.ID = kong.String(d.Id()) + } + return workspace +} diff --git a/kong/resource_kong_workspace_test.go b/kong/resource_kong_workspace_test.go new file mode 100644 index 0000000..a5eb440 --- /dev/null +++ b/kong/resource_kong_workspace_test.go @@ -0,0 +1,127 @@ +package kong + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/kong/go-kong/kong" +) + +func TestAccKongWorkspace(t *testing.T) { + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckKongWorkspaceDestroy, + Steps: []resource.TestStep{ + { + Config: testWorkspaceConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckKongWorkspaceExists("kong_workspace.workspace"), + resource.TestCheckResourceAttr("kong_workspace.workspace", "name", "myworkspace"), + ), + }, + { + Config: testUpdateWorkspaceConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckKongWorkspaceExists("kong_workspace.workspace"), + resource.TestCheckResourceAttr("kong_workspace.workspace", "name", "yourworkspace"), + ), + }, + }, + }) +} + +func TestAccKongWorkspaceImport(t *testing.T) { + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckKongWorkspaceDestroy, + Steps: []resource.TestStep{ + { + Config: testWorkspaceConfig, + }, + { + ResourceName: "kong_workspace.workspace", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckKongWorkspaceDestroy(state *terraform.State) error { + + client := testAccProvider.Meta().(*config).adminClient.Workspaces + + workspaces := getResourcesByType("kong_workspace", state) + + if len(workspaces) > 1 { + return fmt.Errorf("expecting max 1 workspace resource, found %v", len(workspaces)) + } + + if len(workspaces) == 0 { + return nil + } + + response, err := client.ListAll(context.Background()) + + if err != nil { + return fmt.Errorf("error thrown when trying to list workspaces: %v", err) + } + + if response != nil { + for _, element := range response { + if *element.ID == workspaces[0].Primary.ID { + return fmt.Errorf("workspace %s still exists, %+v", workspaces[0].Primary.ID, response) + } + } + } + + return nil +} + +func testAccCheckKongWorkspaceExists(resourceKey string) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceKey] + + if !ok { + return fmt.Errorf("not found: %s", resourceKey) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("no ID is set") + } + + client := testAccProvider.Meta().(*config).adminClient.Workspaces + workspaces, err := client.ListAll(context.Background()) + + if !kong.IsNotFoundErr(err) && err != nil { + return err + } + + if workspaces == nil { + return fmt.Errorf("workspace with id %v not found", rs.Primary.ID) + } + + if len(workspaces) != 2 { + return fmt.Errorf("expected two workspaces (default & just-created), found %v", len(workspaces)) + } + + return nil + } +} + +const testWorkspaceConfig = ` +resource "kong_workspace" "workspace" { + name = "myworkspace" +} +` +const testUpdateWorkspaceConfig = ` +resource "kong_workspace" "workspace" { + name = "yourworkspace" +} +`