Skip to content

Commit

Permalink
Add user token resource (#11)
Browse files Browse the repository at this point in the history
* Add user token support

* Add integration tests
  • Loading branch information
gaetan-craft authored Jun 25, 2022
1 parent e67330a commit 509e9c4
Show file tree
Hide file tree
Showing 11 changed files with 368 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docs/resources/user_token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Resource: graylog_user_token

* [Example](https://github.com/terraform-provider-graylog/terraform-provider-graylog/blob/master/examples/v0.12/user_token.tf)
* [Source Code](https://github.com/terraform-provider-graylog/terraform-provider-graylog/blob/master/graylog/resource/user/token/resource.go)

## Argument Reference

* `user_id` - (Required, Forces new resource) The id of the user. The data type is string
* `name` - (Required, Forces new resource) The name of the token. The data type is string

## Attributes Reference

* `token` - The generated token. The data type is `string`

## Import

`graylog_user_token` can be imported using the `user_id:id`, e.g.
```
$ terraform import graylog_user_token.foo 123456:12345678
```
Even it's not very useful since token won't be set due to graylog API
14 changes: 14 additions & 0 deletions examples/v0.12/user_token.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "graylog_user" "test" {
username = "test"
email = "test@example.com"
password = "password"
full_name = "test test"
roles = [
"Reader",
]
}

resource "graylog_user_token" "token" {
user_id = graylog_user.test.id
name = "mytoken"
}
5 changes: 5 additions & 0 deletions graylog/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/zahiar/terraform-provider-graylog/graylog/client/system/pipeline/pipeline"
"github.com/zahiar/terraform-provider-graylog/graylog/client/system/pipeline/rule"
"github.com/zahiar/terraform-provider-graylog/graylog/client/user"
userToken "github.com/zahiar/terraform-provider-graylog/graylog/client/user/token"
"github.com/zahiar/terraform-provider-graylog/graylog/client/view"
"github.com/zahiar/terraform-provider-graylog/graylog/config"
)
Expand Down Expand Up @@ -62,6 +63,7 @@ type Client struct {
StreamRule streamRule.Client
View view.Client
User user.Client
UserToken userToken.Client
}

func New(m interface{}) (Client, error) {
Expand Down Expand Up @@ -159,5 +161,8 @@ func New(m interface{}) (Client, error) {
User: user.Client{
Client: httpClient,
},
UserToken: userToken.Client{
Client: httpClient,
},
}, nil
}
62 changes: 62 additions & 0 deletions graylog/client/user/token/token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package token

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

"github.com/suzuki-shunsuke/go-httpclient/httpclient"
)

type Client struct {
Client httpclient.Client
}

func (cl Client) Get(
ctx context.Context, user_id string, id string, api_version string,
) (map[string]interface{}, *http.Response, error) {

if user_id == "" {
return nil, nil, fmt.Errorf("User id has to be filed")
}
body := map[string][]map[string]interface{}{}
resp, err := cl.Client.Call(ctx, httpclient.CallParams{
Method: "GET",
Path: "/users/" + user_id + "/tokens",
ResponseBody: &body,
})
if err != nil {
return nil, nil, err
}
tokens := body["tokens"]
for token := range tokens {
if tokens[token]["id"] == id {
return tokens[token], resp, err
}
}
resp.StatusCode = http.StatusNotFound
return make(map[string]interface{}), resp, fmt.Errorf("No token found")
}

func (cl Client) Create(ctx context.Context, token map[string]interface{}) (map[string]interface{}, *http.Response, error) {
if token == nil {
return nil, nil, errors.New("request body is nil")
}

body := map[string]interface{}{}
resp, err := cl.Client.Call(ctx, httpclient.CallParams{
Method: "POST",
Path: "/users/" + token["user_id"].(string) + "/tokens/" + token["name"].(string),
ResponseBody: &body,
})
return body, resp, err
}

func (cl Client) Delete(ctx context.Context, user_id string, id string) (*http.Response, error) {
resp, err := cl.Client.Call(ctx, httpclient.CallParams{
Method: "DELETE",
Path: "/users/" + user_id + "/tokens/" + id,
})
return resp, err
}
31 changes: 31 additions & 0 deletions graylog/resource/user/token/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package token

import (
"context"

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

"github.com/zahiar/terraform-provider-graylog/graylog/client"
)

func create(d *schema.ResourceData, m interface{}) error {
ctx := context.Background()
cl, err := client.New(m)
if err != nil {
return err
}
data, err := getDataFromResourceData(d)
if err != nil {
return err
}
data, _, err = cl.UserToken.Create(ctx, data)
if err != nil {
return err
}
err = d.Set("token", data["token"])
if err != nil {
return err
}
d.SetId(data["id"].(string))
return nil
}
21 changes: 21 additions & 0 deletions graylog/resource/user/token/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package token

import (
"context"

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

"github.com/zahiar/terraform-provider-graylog/graylog/client"
)

func destroy(d *schema.ResourceData, m interface{}) error {
ctx := context.Background()
cl, err := client.New(m)
if err != nil {
return err
}
if _, err := cl.UserToken.Delete(ctx, d.Get("user_id").(string), d.Id()); err != nil {
return err
}
return nil
}
24 changes: 24 additions & 0 deletions graylog/resource/user/token/read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package token

import (
"context"

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

"github.com/zahiar/terraform-provider-graylog/graylog/client"
"github.com/zahiar/terraform-provider-graylog/graylog/util"
)

func read(d *schema.ResourceData, m interface{}) error {
ctx := context.Background()
cl, err := client.New(m)
if err != nil {
return err
}
data, resp, err := cl.UserToken.Get(ctx, d.Get("user_id").(string), d.Id(), cl.APIVersion)
if err != nil {
return util.HandleGetResourceError(d, resp, err)
}
return setDataToResourceData(d, data, cl.APIVersion)

}
49 changes: 49 additions & 0 deletions graylog/resource/user/token/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package token

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"strings"
)

func Resource() *schema.Resource {
return &schema.Resource{
Create: create,
Read: read,
Delete: destroy,

Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.SplitN(d.Id(), ":", 2)

if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return nil, fmt.Errorf("unexpected format of ID (%s), expected attribute1:attribute2", d.Id())
}
err := d.Set("user_id", parts[0])
if err != nil {
return nil, err
}
d.SetId(parts[1])
return []*schema.ResourceData{d}, nil
},
},

Schema: map[string]*schema.Schema{
"user_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"token": {
Type: schema.TypeString,
Computed: true,
Sensitive: true,
},
},
}
}
116 changes: 116 additions & 0 deletions graylog/resource/user/token/resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package token

import (
"io/ioutil"
"net/http"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/suzuki-shunsuke/flute/v2/flute"

"github.com/zahiar/terraform-provider-graylog/graylog/testutil"
)

const testUserId = "62aca4d45036cb55b711f258"

func TestAccUserToken(t *testing.T) {
if err := testutil.SetEnv(); err != nil {
t.Fatal(err)
}

getRoute := flute.Route{
Name: "get user tokens",
Matcher: flute.Matcher{
Method: "GET",
},
Response: flute.Response{
Response: func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader(`{
"tokens": [
{
"id": "62aca4d45036cb55b711f259",
"last_access": "1970-01-01T00:00:00.000Z",
"name": "toto"
},
{
"id": "62acf0095036cb55b71202f7",
"last_access": "1970-01-01T00:00:00.000Z",
"name": "truc"
}
]
}`)),
}, nil
},
},
}

postRoute := flute.Route{
Name: "create a user token",
Matcher: flute.Matcher{
Method: "POST",
},
Tester: flute.Tester{
Path: "/api/users/" + testUserId + "/tokens/toto",
PartOfHeader: testutil.Header(),
},
Response: flute.Response{
Response: func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader(`{
"id": "62aca4d45036cb55b711f259",
"last_access": "1970-01-01T00:00:00.000Z",
"name": "toto",
"token": "10asfgsjp43de53io0cjc9ttj3r002tq26qai278ac57lhrb8p3r"
}`)),
}, nil
},
},
}

deleteRoute := flute.Route{
Name: "delete a user token",
Matcher: flute.Matcher{
Method: "DELETE",
},
Tester: flute.Tester{
Path: "/api/users/" + testUserId + "/tokens/62aca4d45036cb55b711f259",
},
Response: flute.Response{
Response: func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 200,
Body: ioutil.NopCloser(strings.NewReader(`{}`)),
}, nil
},
},
}

createStep := resource.TestStep{
ResourceName: "graylog_user_token.test",
PreConfig: func() {
testutil.SetHTTPClient(t, getRoute, postRoute, deleteRoute)
},
Config: `
resource "graylog_user_token" "test" {
user_id = "` + testUserId + `"
name = "toto"
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("graylog_user_token.test", "name", "toto"),
resource.TestCheckResourceAttr("graylog_user_token.test", "user_id", testUserId),
resource.TestCheckResourceAttr("graylog_user_token.test", "token", "10asfgsjp43de53io0cjc9ttj3r002tq26qai278ac57lhrb8p3r"),
),
}

resource.Test(t, resource.TestCase{
Providers: testutil.SingleResourceProviders("graylog_user_token", Resource()),
Steps: []resource.TestStep{
createStep,
},
})
}
23 changes: 23 additions & 0 deletions graylog/resource/user/token/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package token

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/zahiar/terraform-provider-graylog/graylog/convert"
)

func getDataFromResourceData(d *schema.ResourceData) (map[string]interface{}, error) {
data, err := convert.GetFromResourceData(d, Resource())
if err != nil {
return nil, err
}
return data, nil
}

func setDataToResourceData(d *schema.ResourceData, data map[string]interface{}, api_version string) error {
if err := convert.SetResourceData(d, Resource(), data); err != nil {
return err
}
d.SetId(data["id"].(string))
return nil
}
Loading

0 comments on commit 509e9c4

Please sign in to comment.