Skip to content

Commit

Permalink
feat: add support for the namespace file resource and datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin GUIBERT committed Oct 26, 2023
1 parent 6ecd198 commit 4e887f2
Show file tree
Hide file tree
Showing 12 changed files with 565 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ jobs:
curl -X POST "127.27.27.27:8080/api/v1/users" > /dev/null
curl -u john@doe.com:pass -X POST -H 'Content-Type: application/json' -d '{"id":"unit_test","name":"Unit Test"}' "127.27.27.27:8080/api/v1/tenants" > /dev/null
curl -H "Content-Type: application/x-ndjson" -XPOST "127.27.27.27:9200/_bulk?pretty" --data-binary @.github/workflows/index.jsonl
curl -u john@doe.com:pass -X POST -F fileContent=@internal/resources/flow.py "127.27.27.27:8080/api/v1/files/namespace/io.kestra.terraform.data?path=/flow.py" > /dev/null
- name: Set up Go
uses: actions/setup-go@v4
Expand Down
39 changes: 39 additions & 0 deletions docs/data-sources/namespace_file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "kestra_namespace_file Data Source - terraform-provider-kestra"
subcategory: ""
description: |-
Use this data source to access information about an existing Namespace File
---

# kestra_namespace_file (Data Source)

Use this data source to access information about an existing Namespace File

## Example Usage

```terraform
data "kestra_namespace_file" "example" {
namespace_ = "io.kestra.mynamespace"
filename = "my-file.yml"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `filename` (String) The path to the namespace file that will be created.
Missing parent directories will be created.
If the file already exists, it will be overridden with the given content.
- `namespace` (String) The Namespace file namespace.

### Optional

- `content` (String) Content to store in the file, expected to be a UTF-8 encoded string.
- `tenant_id` (String) The tenant id.

### Read-Only

- `id` (String) The ID of this resource.
62 changes: 62 additions & 0 deletions docs/resources/namespace_file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "kestra_namespace_file Resource - terraform-provider-kestra"
subcategory: ""
description: |-
Manages a Kestra Namespace File.
---

# kestra_namespace_file (Resource)

Manages a Kestra Namespace File.

## Example Usage

```terraform
resource "kestra_namespace_file" "example" {
namespace = "io.kestra.mynamespace"
filename = "/path/my-file.sh"
content = <<EOT
#!/bin/bash
echo "Hello World"
EOT
}
resource "kestra_namespace_file" "withsource" {
namespace = "io.kestra.mynamespace"
filename = "/path/my-file.sh"
content = "./kestra/file.sh"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `filename` (String) The path to the namespace file that will be created.
Missing parent directories will be created.
If the file already exists, it will be overridden with the given content.
- `namespace` (String) The Namespace file namespace.

### Optional

- `content` (String) Content to store in the file, expected to be a UTF-8 encoded string.
Conflicts with `source`.
Exactly one of these four arguments must be specified.
- `source` (String) Path to file to use as source for the one we are creating.
Conflicts with `content`.
Exactly one of these four arguments must be specified.
- `tenant_id` (String) The tenant id.

### Read-Only

- `id` (String) The ID of this resource.

## Import

Import is supported using the following syntax:

```shell
terraform import kestra_namespace_file.example {{namespace}}/{{filename}}
```
4 changes: 4 additions & 0 deletions examples/data-sources/kestra_namespace_file/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
data "kestra_namespace_file" "example" {
namespace_ = "io.kestra.mynamespace"
filename = "my-file.yml"
}
1 change: 1 addition & 0 deletions examples/resources/kestra_namespace_file/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import kestra_namespace_file.example {{namespace}}/{{filename}}
14 changes: 14 additions & 0 deletions examples/resources/kestra_namespace_file/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "kestra_namespace_file" "example" {
namespace = "io.kestra.mynamespace"
filename = "/path/my-file.sh"
content = <<EOT
#!/bin/bash
echo "Hello World"
EOT
}

resource "kestra_namespace_file" "withsource" {
namespace = "io.kestra.mynamespace"
filename = "/path/my-file.sh"
content = "./kestra/file.sh"
}
52 changes: 30 additions & 22 deletions internal/provider/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,31 @@ func (c *Client) yamlRequest(method, url string, body *string) (interface{}, *Re
}

func (c *Client) rawRequest(method, url string, req *http.Request) (interface{}, *RequestError) {
statusCode, bodyResult, reqErr := c.rawResponseRequest(method, req)
if reqErr != nil {
return nil, reqErr
}

log.Printf("[DEBUG] Response from %s %s: %s\n", method, c.Url+url, bodyResult)

var jsonDecoded interface{}
if string(bodyResult) != "" {
decoder := json.NewDecoder(bytes.NewReader(bodyResult))
decoder.UseNumber()

err := decoder.Decode(&jsonDecoded)
if err != nil {
return nil, &RequestError{
StatusCode: statusCode,
Err: err,
}
}
}

return jsonDecoded, nil
}

func (c *Client) rawResponseRequest(method string, req *http.Request) (int, []byte, *RequestError) {
if (c.Username != nil) && (c.Password != nil) {
req.SetBasicAuth(
*c.Username,
Expand All @@ -115,49 +140,32 @@ func (c *Client) rawRequest(method, url string, req *http.Request) (interface{},

res, err := c.HTTPClient.Do(req)
if (err != nil) && (res != nil) {
return nil, &RequestError{
return 0, nil, &RequestError{
StatusCode: res.StatusCode,
Err: err,
}
} else if err != nil {
return nil, &RequestError{
return 0, nil, &RequestError{
StatusCode: 0,
Err: err,
}
}

defer res.Body.Close()

bodyResult, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, &RequestError{
return 0, nil, &RequestError{
StatusCode: res.StatusCode,
Err: err,
}
}

log.Printf("[DEBUG] Response from %s %s: %s\n", method, c.Url+url, bodyResult)

if (res.StatusCode != http.StatusOK) && (res.StatusCode != http.StatusNoContent) {
return nil, &RequestError{
return 0, nil, &RequestError{
StatusCode: res.StatusCode,
Err: fmt.Errorf("status: %d, method: %s, body: %s", res.StatusCode, method, bodyResult),
}
}

var jsonDecoded interface{}
if string(bodyResult) != "" {
decoder := json.NewDecoder(bytes.NewReader(bodyResult))
decoder.UseNumber()

err = decoder.Decode(&jsonDecoded)
if err != nil {
return nil, &RequestError{
StatusCode: res.StatusCode,
Err: err,
}
}
}

return jsonDecoded, nil
return res.StatusCode, bodyResult, nil
}
85 changes: 85 additions & 0 deletions internal/provider/data_source_namespace_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package provider

import (
"context"
"fmt"
"net/http"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceNamespaceFile() *schema.Resource {
return &schema.Resource{
Description: "Use this data source to access information about an existing Namespace File",

ReadContext: dataSourceNamespaceFileRead,
Schema: map[string]*schema.Schema{
"tenant_id": {
Description: "The tenant id.",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"namespace": {
Description: "The Namespace file namespace.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"filename": {
Description: "The path to the namespace file that will be created.\n" +
"Missing parent directories will be created.\n" +
"If the file already exists, it will be overridden with the given content.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"content": {
Description: "Content to store in the file, expected to be a UTF-8 encoded string.",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
},
}
}

func dataSourceNamespaceFileRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
c := meta.(*Client)
var diags diag.Diagnostics

namespace := d.Get("namespace").(string)
filename := d.Get("filename").(string)
tenantId := d.Get("tenant_id").(string)

url := c.Url + fmt.Sprintf("%s/files/namespaces/%s?path=%s", apiRoot(tenantId), namespace, filename)

req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf(url), nil)
if err != nil {
return diag.FromErr(err)
}

statusCode, body, reqErr := c.rawResponseRequest("GET", req)
if reqErr != nil {
if statusCode == http.StatusNotFound {
d.SetId("")
return diags
}
return diag.FromErr(reqErr.Err)
}

d.SetId(fmt.Sprintf("%s/%s", namespace, filename))
if err := d.Set("namespace", namespace); err != nil {
return diag.FromErr(err)
}
if err := d.Set("filename", filename); err != nil {
return diag.FromErr(err)
}
if err := d.Set("content", string(body)); err != nil {
return diag.FromErr(err)
}

return diags
}
37 changes: 37 additions & 0 deletions internal/provider/data_source_namespace_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package provider

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccDataSourceNamespaceFile(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccDataSourceNamespaceFile("io.kestra.terraform.data", "/flow.py"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"data.kestra_template.new", "filename", "/flow.py",
),
),
},
},
})
}

func testAccDataSourceNamespaceFile(namespace, filename string) string {
return fmt.Sprintf(
`
data "kestra_namespace_file" "new" {
namespace = "%s"
filename = "%s"
}`,
namespace,
filename,
)
}
18 changes: 10 additions & 8 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@ func New(version string) func() *schema.Provider {
},
},
DataSourcesMap: map[string]*schema.Resource{
"kestra_binding": dataSourceBinding(),
"kestra_flow": dataSourceFlow(),
"kestra_group": dataSourceGroup(),
"kestra_namespace": dataSourceNamespace(),
"kestra_role": dataSourceRole(),
"kestra_template": dataSourceTemplate(),
"kestra_user": dataSourceUser(),
"kestra_tenant": dataSourceTenant(),
"kestra_binding": dataSourceBinding(),
"kestra_flow": dataSourceFlow(),
"kestra_group": dataSourceGroup(),
"kestra_namespace": dataSourceNamespace(),
"kestra_role": dataSourceRole(),
"kestra_template": dataSourceTemplate(),
"kestra_user": dataSourceUser(),
"kestra_tenant": dataSourceTenant(),
"kestra_namespace_file": dataSourceNamespaceFile(),
},
ResourcesMap: map[string]*schema.Resource{
"kestra_binding": resourceBinding(),
Expand All @@ -77,6 +78,7 @@ func New(version string) func() *schema.Provider {
"kestra_user": resourceUser(),
"kestra_user_password": resourceUserPassword(),
"kestra_tenant": resourceTenant(),
"kestra_namespace_file": resourceNamespaceFile(),
},
}

Expand Down
Loading

0 comments on commit 4e887f2

Please sign in to comment.