From 058bb74f14c077801c6bce53fb196bc17c6a83bb Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Fri, 15 Nov 2024 14:54:01 +0100 Subject: [PATCH 1/2] WIP: resourcepools resources Signed-off-by: Danny Kopping --- provider/pool_resource_claim.go | 97 +++++++++++++++++++++++++++++++++ provider/provider.go | 14 +++-- 2 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 provider/pool_resource_claim.go diff --git a/provider/pool_resource_claim.go b/provider/pool_resource_claim.go new file mode 100644 index 00000000..e5bfbdf7 --- /dev/null +++ b/provider/pool_resource_claim.go @@ -0,0 +1,97 @@ +package provider + +import ( + "context" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func poolResourceClaimResource() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + Description: "Use this resource to claim a resource pool entry.", + CreateContext: func(_ context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + resourceData.SetId(uuid.NewString()) + return nil + }, + ReadContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + // poolb64 := base64.StdEncoding.EncodeToString([]byte(resourceData.Get("pool_name").(string))) + // key := fmt.Sprintf("CODER_RESOURCE_POOL_%s_ENTRY_OBJECT_ID", poolb64) + // objectId, err := helpers.RequireEnv(key) + // if err != nil { + // return diag.Errorf("resource pool entry object ID not found in env %q: %s", key, err) + // } + // + // if err = resourceData.Set("object_id", objectId); err != nil { + // return diag.Errorf("failed to set resource pool entry object ID: %s", err) + // } + return nil + }, + DeleteContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + return nil + }, + Schema: map[string]*schema.Schema{ + "pool_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The name of the pool from which an entry will be claimed.", + }, + "object_id": { + Type: schema.TypeString, + Computed: true, + Description: "The object ID of the pooled entry resource", + }, + }, + } +} + +func poolResourceClaimableResource() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + Description: "Use this resource to specify which resources are claimable by workspaces.", + CreateContext: func(_ context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + resourceData.SetId(uuid.NewString()) + return nil + }, + ReadContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + return nil + }, + DeleteContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + return nil + }, + Schema: map[string]*schema.Schema{ + "compute": { + Type: schema.TypeSet, + ForceNew: true, + Optional: true, + ConflictsWith: []string{"other"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Description: "The ID of the compute instance (container/VM/etc).", + ForceNew: true, + Required: true, + }, + "agent_id": { + Type: schema.TypeString, + Description: "The ID of the agent running inside the compute instance.", + ForceNew: true, + Required: true, + }, + }, + }, + }, + "other": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + }, + }, + } +} diff --git a/provider/provider.go b/provider/provider.go index 1d78f2dd..3765d5e0 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -69,12 +69,14 @@ func New() *schema.Provider { "coder_workspace_owner": workspaceOwnerDataSource(), }, ResourcesMap: map[string]*schema.Resource{ - "coder_agent": agentResource(), - "coder_agent_instance": agentInstanceResource(), - "coder_app": appResource(), - "coder_metadata": metadataResource(), - "coder_script": scriptResource(), - "coder_env": envResource(), + "coder_agent": agentResource(), + "coder_agent_instance": agentInstanceResource(), + "coder_app": appResource(), + "coder_metadata": metadataResource(), + "coder_script": scriptResource(), + "coder_env": envResource(), + "coder_pool_resource_claim": poolResourceClaimResource(), + "coder_pool_resource_claimable": poolResourceClaimableResource(), }, } } From 7f0dab99d59d541c566a217c2aa9526a28d196f5 Mon Sep 17 00:00:00 2001 From: Danny Kopping Date: Wed, 11 Dec 2024 11:16:29 +0200 Subject: [PATCH 2/2] Inject instance IDs in by pool name Signed-off-by: Danny Kopping --- provider/pool_resource_claim.go | 51 +++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/provider/pool_resource_claim.go b/provider/pool_resource_claim.go index e5bfbdf7..64d30b8f 100644 --- a/provider/pool_resource_claim.go +++ b/provider/pool_resource_claim.go @@ -2,7 +2,11 @@ package provider import ( "context" + "crypto/sha1" + "encoding/base32" + "fmt" + "github.com/coder/terraform-provider-coder/provider/helpers" "github.com/google/uuid" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -15,22 +19,28 @@ func poolResourceClaimResource() *schema.Resource { Description: "Use this resource to claim a resource pool entry.", CreateContext: func(_ context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { resourceData.SetId(uuid.NewString()) + + pool := resourceData.Get("pool_name").(string) + + // SHA-1 because Base32/64 produces an invalid env infix + poolName := sha1.Sum([]byte(pool)) + key := fmt.Sprintf("CODER_RESOURCEPOOL_%x_ENTRY_INSTANCE_ID", poolName) + instanceId, err := helpers.RequireEnv(key) + if err != nil { + return diag.Errorf("failed to get instance ID: %s", err.Error()) + } + decoded, err := base32.StdEncoding.DecodeString(instanceId) + if err != nil { + return diag.Errorf("failed to decode instance ID %q: %s", instanceId, err.Error()) + } + _ = resourceData.Set("instance_id", string(decoded)) + return nil }, - ReadContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { - // poolb64 := base64.StdEncoding.EncodeToString([]byte(resourceData.Get("pool_name").(string))) - // key := fmt.Sprintf("CODER_RESOURCE_POOL_%s_ENTRY_OBJECT_ID", poolb64) - // objectId, err := helpers.RequireEnv(key) - // if err != nil { - // return diag.Errorf("resource pool entry object ID not found in env %q: %s", key, err) - // } - // - // if err = resourceData.Set("object_id", objectId); err != nil { - // return diag.Errorf("failed to set resource pool entry object ID: %s", err) - // } + ReadContext: func(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics { return nil }, - DeleteContext: func(ctx context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics { + DeleteContext: func(ctx context.Context, data *schema.ResourceData, i interface{}) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -40,10 +50,10 @@ func poolResourceClaimResource() *schema.Resource { ForceNew: true, Description: "The name of the pool from which an entry will be claimed.", }, - "object_id": { + "instance_id": { Type: schema.TypeString, Computed: true, - Description: "The object ID of the pooled entry resource", + Description: "The instance ID of the pooled entry resource", }, }, } @@ -88,9 +98,20 @@ func poolResourceClaimableResource() *schema.Resource { }, }, "other": { - Type: schema.TypeString, + Type: schema.TypeSet, ForceNew: true, Optional: true, + + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Description: "The ID of the instance.", + ForceNew: true, + Required: true, + }, + }, + }, }, }, }