diff --git a/docs/resources/custom_plugin_schema.md b/docs/resources/custom_plugin_schema.md new file mode 100644 index 0000000..9aa3193 --- /dev/null +++ b/docs/resources/custom_plugin_schema.md @@ -0,0 +1,24 @@ +--- +subcategory: "Runtime Configuration" +--- +# Resource: konnect_custom_plugin_schema +Represents a custom plugin schema within a control plane +## Example usage +```hcl +data "konnect_control_plane" "ControlPlane" { + name = "TestControlPlane" +} +resource "konnect_custom_plugin_schema" "example" { + control_plane_id = data.konnect_control_plane.ControlPlane.id + name = "my-plugin" + schema_lua = "return { name=\"my-plugin\", fields = { { config = { type = \"record\", fields = { } } } } }" +} +``` +## Argument Reference +* `control_plane_id` - **(Required, String)** The id of the control plane. +* `name` - **(Required, ForceNew, String)** The name of the custom plugin schema. +* `schema_lua` - **(Required, String)** The lua code that defines the schema. Typically, this is the content of the custom plugin schema.lua file. +## Attribute Reference +* `id` - **(String)** Same as `control_plane_id`:`name` +## Import +Custom plugin schemas can be imported using a proper value of `id` as described above diff --git a/konnect/client/custom_plugin_schema.go b/konnect/client/custom_plugin_schema.go new file mode 100644 index 0000000..b3b2e0c --- /dev/null +++ b/konnect/client/custom_plugin_schema.go @@ -0,0 +1,26 @@ +package client + +import "strings" + +const ( + CustomPluginSchemaPath = ControlPlanePathGet + "/core-entities/plugin-schemas" + CustomPluginSchemaPathGet = CustomPluginSchemaPath + "/%s" +) + +type CustomPluginSchema struct { + ControlPlaneId string `json:"-"` + Name string `json:"name"` + SchemaLua string `json:"lua_schema"` +} +type CustomPluginSchemaItem struct { + Item CustomPluginSchema `json:"item"` +} + +func (s *CustomPluginSchema) CustomPluginSchemaEncodeId() string { + return s.ControlPlaneId + IdSeparator + s.Name +} + +func CustomPluginSchemaDecodeId(s string) (string, string) { + tokens := strings.Split(s, IdSeparator) + return tokens[0], tokens[1] +} diff --git a/konnect/provider.go b/konnect/provider.go index f732ed6..99b82f5 100644 --- a/konnect/provider.go +++ b/konnect/provider.go @@ -49,6 +49,7 @@ func Provider() *schema.Provider { "konnect_consumer_hmac": resourceConsumerHMAC(), "konnect_consumer_jwt": resourceConsumerJWT(), "konnect_plugin": resourcePlugin(), + "konnect_custom_plugin_schema": resourceCustomPluginSchema(), }, DataSourcesMap: map[string]*schema.Resource{ "konnect_control_plane": dataSourceControlPlane(), diff --git a/konnect/resource_custom_plugin_schema.go b/konnect/resource_custom_plugin_schema.go new file mode 100644 index 0000000..67ad473 --- /dev/null +++ b/konnect/resource_custom_plugin_schema.go @@ -0,0 +1,151 @@ +package konnect + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "github.com/go-http-utils/headers" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/scastria/terraform-provider-konnect/konnect/client" + "net/http" +) + +func resourceCustomPluginSchema() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceCustomPluginSchemaCreate, + ReadContext: resourceCustomPluginSchemaRead, + UpdateContext: resourceCustomPluginSchemaUpdate, + DeleteContext: resourceCustomPluginSchemaDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Schema: map[string]*schema.Schema{ + "control_plane_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "schema_lua": { + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func fillCustomPluginSchema(c *client.CustomPluginSchema, d *schema.ResourceData) { + c.ControlPlaneId = d.Get("control_plane_id").(string) + c.Name = d.Get("name").(string) + c.SchemaLua = d.Get("schema_lua").(string) +} + +func fillResourceDataFromCustomPluginSchema(c *client.CustomPluginSchema, d *schema.ResourceData) { + d.Set("control_plane_id", c.ControlPlaneId) + d.Set("name", c.Name) + d.Set("schema_lua", c.SchemaLua) +} + +func resourceCustomPluginSchemaCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + var diags diag.Diagnostics + c := m.(*client.Client) + buf := bytes.Buffer{} + newCustomPluginSchema := client.CustomPluginSchema{} + fillCustomPluginSchema(&newCustomPluginSchema, d) + err := json.NewEncoder(&buf).Encode(newCustomPluginSchema) + if err != nil { + d.SetId("") + return diag.FromErr(err) + } + requestPath := fmt.Sprintf(client.CustomPluginSchemaPath, newCustomPluginSchema.ControlPlaneId) + requestHeaders := http.Header{ + headers.ContentType: []string{client.ApplicationJson}, + } + body, err := c.HttpRequest(ctx, true, http.MethodPost, requestPath, nil, requestHeaders, &buf) + if err != nil { + d.SetId("") + return diag.FromErr(err) + } + retVal := &client.CustomPluginSchemaItem{} + err = json.NewDecoder(body).Decode(retVal) + if err != nil { + d.SetId("") + return diag.FromErr(err) + } + retVal.Item.ControlPlaneId = newCustomPluginSchema.ControlPlaneId + d.SetId(retVal.Item.CustomPluginSchemaEncodeId()) + fillResourceDataFromCustomPluginSchema(&(retVal.Item), d) + return diags +} + +func resourceCustomPluginSchemaRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + var diags diag.Diagnostics + controlPlaneId, name := client.CustomPluginSchemaDecodeId(d.Id()) + c := m.(*client.Client) + requestPath := fmt.Sprintf(client.CustomPluginSchemaPathGet, controlPlaneId, name) + body, err := c.HttpRequest(ctx, true, http.MethodGet, requestPath, nil, nil, &bytes.Buffer{}) + if err != nil { + d.SetId("") + re := err.(*client.RequestError) + if re.StatusCode == http.StatusNotFound { + return diags + } + return diag.FromErr(err) + } + retVal := &client.CustomPluginSchemaItem{} + err = json.NewDecoder(body).Decode(retVal) + if err != nil { + d.SetId("") + return diag.FromErr(err) + } + retVal.Item.ControlPlaneId = controlPlaneId + fillResourceDataFromCustomPluginSchema(&(retVal.Item), d) + return diags +} + +func resourceCustomPluginSchemaUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + var diags diag.Diagnostics + controlPlaneId, name := client.CustomPluginSchemaDecodeId(d.Id()) + c := m.(*client.Client) + buf := bytes.Buffer{} + upCustomPluginSchema := client.CustomPluginSchema{} + fillCustomPluginSchema(&upCustomPluginSchema, d) + err := json.NewEncoder(&buf).Encode(upCustomPluginSchema) + if err != nil { + return diag.FromErr(err) + } + requestPath := fmt.Sprintf(client.CustomPluginSchemaPathGet, controlPlaneId, name) + requestHeaders := http.Header{ + headers.ContentType: []string{client.ApplicationJson}, + } + body, err := c.HttpRequest(ctx, true, http.MethodPut, requestPath, nil, requestHeaders, &buf) + if err != nil { + return diag.FromErr(err) + } + retVal := &client.CustomPluginSchemaItem{} + err = json.NewDecoder(body).Decode(retVal) + if err != nil { + return diag.FromErr(err) + } + retVal.Item.ControlPlaneId = controlPlaneId + fillResourceDataFromCustomPluginSchema(&(retVal.Item), d) + return diags +} + +func resourceCustomPluginSchemaDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + var diags diag.Diagnostics + controlPlaneId, name := client.CustomPluginSchemaDecodeId(d.Id()) + c := m.(*client.Client) + requestPath := fmt.Sprintf(client.CustomPluginSchemaPathGet, controlPlaneId, name) + _, err := c.HttpRequest(ctx, true, http.MethodDelete, requestPath, nil, nil, &bytes.Buffer{}) + if err != nil { + return diag.FromErr(err) + } + d.SetId("") + return diags +} diff --git a/test/main.tf b/test/main.tf index c06df5d..33202fe 100644 --- a/test/main.tf +++ b/test/main.tf @@ -9,6 +9,12 @@ terraform { provider "konnect" { } +# resource "konnect_custom_plugin_schema" "CPS" { +# control_plane_id = data.konnect_control_plane.RG.id +# name = "shawn" +# schema_lua = "return { name=\"shawn\", fields = { { config = { type = \"record\", fields = { } } } } }" +# } + #resource "konnect_plugin" "P" { # control_plane_id = data.konnect_control_plane.RG.id # name = "rate-limiting"