Skip to content

Commit c00f954

Browse files
committed
Added username/password configuration options
1 parent 83023d4 commit c00f954

File tree

9 files changed

+87
-98
lines changed

9 files changed

+87
-98
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
## 0.1.0 (Unreleased)
1+
## 0.1.1 (Unreleased)
22

33
BACKWARDS INCOMPATIBILITIES / NOTES:

README.md

Lines changed: 3 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,5 @@
1-
# Terraform Provider Scaffolding
1+
# Terraform Provider for Mreg
22

3-
This repository is a *template* for a [Terraform](https://www.terraform.io) provider. It is intended as a starting point for creating Terraform providers, containing:
3+
This Terraform provider gives you a way to interact with [Mreg](https://github.com/unioslo/mreg/) through the API.
44

5-
- A resource, and a data source (`internal/provider/`),
6-
- Examples (`examples/`) and generated documentation (`docs/`),
7-
- Miscellaneous meta files.
8-
9-
These files contain boilerplate code that you will need to edit to create your own Terraform provider. A full guide to creating Terraform providers can be found at [Writing Custom Providers](https://www.terraform.io/docs/extend/writing-custom-providers.html).
10-
11-
Please see the [GitHub template repository documentation](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template) for how to create a new repository from this template on GitHub.
12-
13-
Once you've written your provider, you'll want to [publish it on the Terraform Registry](https://www.terraform.io/docs/registry/providers/publishing.html) so that others can use it.
14-
15-
16-
## Requirements
17-
18-
- [Terraform](https://www.terraform.io/downloads.html) >= 0.13.x
19-
- [Go](https://golang.org/doc/install) >= 1.15
20-
21-
## Building The Provider
22-
23-
1. Clone the repository
24-
1. Enter the repository directory
25-
1. Build the provider using the Go `install` command:
26-
```sh
27-
$ go install
28-
```
29-
30-
## Adding Dependencies
31-
32-
This provider uses [Go modules](https://github.com/golang/go/wiki/Modules).
33-
Please see the Go documentation for the most up to date information about using Go modules.
34-
35-
To add a new dependency `github.com/author/dependency` to your Terraform provider:
36-
37-
```
38-
go get github.com/author/dependency
39-
go mod tidy
40-
```
41-
42-
Then commit the changes to `go.mod` and `go.sum`.
43-
44-
## Using the provider
45-
46-
Fill this in for each provider
47-
48-
## Developing the Provider
49-
50-
If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (see [Requirements](#requirements) above).
51-
52-
To compile the provider, run `go install`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory.
53-
54-
To generate or update documentation, run `go generate`.
55-
56-
In order to run the full suite of Acceptance tests, run `make testacc`.
57-
58-
*Note:* Acceptance tests create real resources, and often cost money to run.
59-
60-
```sh
61-
$ make testacc
62-
```
5+
This repository is based on the [Terraform Provider Scaffolding](https://github.com/hashicorp/terraform-provider-scaffolding) repository.

docs/index.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,20 @@ The Mreg provider provides resources to interact with [Mreg](https://github.com/
1616
token = "1234567890ABCDEF"
1717
}
1818

19+
#### Alternatively, supply a username and password:
20+
21+
provider "mreg" {
22+
serverurl = "https://mreg.example.com/"
23+
username = "bob"
24+
password = "secret123"
25+
}
26+
1927
### Required configuration options
2028

2129
- **serverurl** (String)
30+
31+
### Either a token or a username and password is required
32+
2233
- **token** (String, Sensitive)
34+
- **username** (String, Sensitive)
35+
- **password** (String, Sensitive)

examples/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
terraform {
22
required_providers {
33
mreg = {
4-
version = "0.1.0"
4+
version = "0.1.1"
55
source = "uio.no/usit/mreg"
66
}
77
}

examples/run_example.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ go get -v
77
go build
88
#TODO after the provider is added to the registry, there's no need to copy the file here
99
rm -rf ~/.terraform.d/plugins/uio.no/usit/mreg/
10-
mkdir -p ~/.terraform.d/plugins/uio.no/usit/mreg/0.1.0/linux_amd64
11-
cp terraform-provider-mreg ~/.terraform.d/plugins/uio.no/usit/mreg/0.1.0/linux_amd64/
10+
mkdir -p ~/.terraform.d/plugins/uio.no/usit/mreg/0.1.1/linux_amd64
11+
cp terraform-provider-mreg ~/.terraform.d/plugins/uio.no/usit/mreg/0.1.1/linux_amd64/
1212
popd >/dev/null
1313
rm -rf .terraform .terraform.lock.hcl terraform.tfstate crash.log
1414
terraform init

internal/provider/utilities.go renamed to internal/provider/apiclient.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,23 @@ import (
77
"io"
88
"io/ioutil"
99
"net/http"
10+
"strings"
1011

1112
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1213
)
1314

14-
func httpRequest(method, urlPath string, requestBody map[string]interface{}, expectedStatus int, apiClient apiClient) (bodyText string, body interface{}, diags diag.Diagnostics) {
15+
type apiClient struct {
16+
Serverurl string
17+
Token string
18+
Username string
19+
Password string
20+
}
21+
22+
func (c apiClient) UrlWithoutSlash() string {
23+
return strings.TrimSuffix(c.Serverurl, "/")
24+
}
25+
26+
func (apiClient apiClient) httpRequest(method, urlPath string, requestBody map[string]interface{}, expectedStatus int) (bodyText string, body interface{}, diags diag.Diagnostics) {
1527
// Turn the request body structure into JSON
1628
var reqBodyReader io.Reader
1729
if requestBody != nil {
@@ -30,10 +42,13 @@ func httpRequest(method, urlPath string, requestBody map[string]interface{}, exp
3042
diags = diag.FromErr(err)
3143
return
3244
}
33-
req.Header.Add("Authorization", "Token "+apiClient.Token)
45+
if apiClient.Token != "" {
46+
req.Header.Add("Authorization", "Token "+apiClient.Token)
47+
}
3448
if reqBodyReader != nil {
3549
req.Header.Add("Content-Type", "application/json")
3650
}
51+
req.Header.Add("User-Agent", "Terraform provider for Mreg")
3752

3853
// Perform the request
3954
response, err := http.DefaultClient.Do(req)
@@ -77,3 +92,22 @@ func httpRequest(method, urlPath string, requestBody map[string]interface{}, exp
7792

7893
return
7994
}
95+
96+
func (c *apiClient) login() diag.Diagnostics {
97+
bodyText, body, diags := c.httpRequest("POST", "/api/token-auth/", map[string]interface{}{
98+
"username": c.Username,
99+
"password": c.Password,
100+
}, http.StatusOK)
101+
if diags != nil {
102+
return diags
103+
}
104+
data, ok := body.(map[string]interface{})
105+
if !ok {
106+
return diag.Errorf("The Mreg token-auth endpoint returned an unexpected result: %s", bodyText)
107+
}
108+
c.Token, ok = data["token"].(string)
109+
if !ok {
110+
return diag.Errorf("The Mreg token-auth endpoint returned an unexpected result: %s", bodyText)
111+
}
112+
return nil
113+
}

internal/provider/provider.go

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package provider
22

33
import (
44
"context"
5-
"strings"
65

76
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
87
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -39,7 +38,17 @@ func New(version string) func() *schema.Provider {
3938
},
4039
"token": &schema.Schema{
4140
Type: schema.TypeString,
42-
Required: true,
41+
Optional: true,
42+
Sensitive: true,
43+
},
44+
"username": &schema.Schema{
45+
Type: schema.TypeString,
46+
Optional: true,
47+
Sensitive: true,
48+
},
49+
"password": &schema.Schema{
50+
Type: schema.TypeString,
51+
Optional: true,
4352
Sensitive: true,
4453
},
4554
},
@@ -51,27 +60,17 @@ func New(version string) func() *schema.Provider {
5160
}
5261
}
5362

54-
type apiClient struct {
55-
// Add whatever fields, client or connection info, etc. here
56-
// you would need to setup to communicate with the upstream
57-
// API.
58-
Serverurl string
59-
Token string
60-
}
61-
62-
func (c apiClient) UrlWithoutSlash() string {
63-
return strings.TrimSuffix(c.Serverurl, "/")
64-
}
65-
6663
func configure(version string, p *schema.Provider) func(context.Context, *schema.ResourceData) (interface{}, diag.Diagnostics) {
6764
return func(c context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
68-
// Setup a User-Agent for your API client (replace the provider name for yours):
69-
// userAgent := p.UserAgent("terraform-provider-scaffolding", version)
70-
// TODO: myClient.UserAgent = userAgent
71-
72-
return apiClient{
65+
client := apiClient{
7366
Serverurl: d.Get("serverurl").(string),
7467
Token: d.Get("token").(string),
75-
}, nil
68+
Username: d.Get("username").(string),
69+
Password: d.Get("password").(string),
70+
}
71+
if client.Username != "" {
72+
client.login()
73+
}
74+
return client, nil
7675
}
7776
}

internal/provider/resource_hosts.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ func resourceHostsCreate(ctx context.Context, d *schema.ResourceData, m interfac
9898
ipaddress = manual_ip
9999
} else {
100100
// Find a free IP address in Mreg
101-
body, _, diags := httpRequest(
101+
body, _, diags := apiClient.httpRequest(
102102
"GET", fmt.Sprintf("/api/v1/networks/%s/first_unused", url.QueryEscape(network)),
103-
nil, http.StatusOK, apiClient)
103+
nil, http.StatusOK)
104104
if len(diags) > 0 {
105105
return diags
106106
}
@@ -115,7 +115,7 @@ func resourceHostsCreate(ctx context.Context, d *schema.ResourceData, m interfac
115115
"contact": contact,
116116
"comment": comment,
117117
}
118-
_, _, diags := httpRequest("POST", "/api/v1/hosts/", request, http.StatusCreated, apiClient)
118+
_, _, diags := apiClient.httpRequest("POST", "/api/v1/hosts/", request, http.StatusCreated)
119119
if len(diags) > 0 {
120120
return diags
121121
}
@@ -156,8 +156,8 @@ func resourceHostsRead(ctx context.Context, d *schema.ResourceData, m interface{
156156
hostname := host["name"].(string)
157157

158158
// Read information about this host from Mreg
159-
_, body, diags := httpRequest("GET", "/api/v1/hosts/"+url.QueryEscape(hostname),
160-
nil, http.StatusOK, apiClient)
159+
_, body, diags := apiClient.httpRequest("GET", "/api/v1/hosts/"+url.QueryEscape(hostname),
160+
nil, http.StatusOK)
161161
if len(diags) > 0 {
162162
return diags
163163
}
@@ -192,8 +192,8 @@ func resourceHostsDelete(ctx context.Context, d *schema.ResourceData, m interfac
192192
hostname := host["name"].(string)
193193

194194
// Delete this host from Mreg
195-
_, _, diags := httpRequest("DELETE", "/api/v1/hosts/"+url.QueryEscape(hostname),
196-
nil, http.StatusNoContent, apiClient)
195+
_, _, diags := apiClient.httpRequest("DELETE", "/api/v1/hosts/"+url.QueryEscape(hostname),
196+
nil, http.StatusNoContent)
197197
if len(diags) > 0 {
198198
return diags
199199
}

internal/provider/resource_srv.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func resourceSRVCreate(ctx context.Context, d *schema.ResourceData, m interface{
5959
apiClient := m.(apiClient)
6060

6161
// Find the host ID in Mreg by looking up the hostname
62-
_, body, diags := httpRequest("GET", "/api/v1/hosts/"+url.QueryEscape(d.Get("target_host").(string)), nil, http.StatusOK, apiClient)
62+
_, body, diags := apiClient.httpRequest("GET", "/api/v1/hosts/"+url.QueryEscape(d.Get("target_host").(string)), nil, http.StatusOK)
6363
if len(diags) > 0 {
6464
return diags
6565
}
@@ -77,7 +77,7 @@ func resourceSRVCreate(ctx context.Context, d *schema.ResourceData, m interface{
7777
"port": d.Get("port"),
7878
"host": hostID,
7979
}
80-
_, _, diags = httpRequest("POST", "/api/v1/srvs/", postdata, http.StatusCreated, apiClient)
80+
_, _, diags = apiClient.httpRequest("POST", "/api/v1/srvs/", postdata, http.StatusCreated)
8181
if len(diags) > 0 {
8282
return diags
8383
}
@@ -97,15 +97,15 @@ func resourceSRVDelete(ctx context.Context, d *schema.ResourceData, m interface{
9797
serviceProtoName := fmt.Sprintf("_%s._%s.%s.", d.Get("service").(string), d.Get("proto").(string), d.Get("name").(string))
9898

9999
// Find the host ID in Mreg by looking up the hostname
100-
_, body, diags := httpRequest("GET", "/api/v1/hosts/"+url.QueryEscape(d.Get("target_host").(string)), nil, http.StatusOK, apiClient)
100+
_, body, diags := apiClient.httpRequest("GET", "/api/v1/hosts/"+url.QueryEscape(d.Get("target_host").(string)), nil, http.StatusOK)
101101
if len(diags) > 0 {
102102
return diags
103103
}
104104
bodyMap := body.(map[string]interface{})
105105
hostID := int(bodyMap["id"].(float64)) // Go always turns JSON numbers into float64 values
106106

107107
// Find all SRV records of that particular type, for that particular host
108-
_, body, diags = httpRequest("GET", fmt.Sprintf("/api/v1/srvs/?host=%d&name=%s", hostID, url.QueryEscape(serviceProtoName)), nil, http.StatusOK, apiClient)
108+
_, body, diags = apiClient.httpRequest("GET", fmt.Sprintf("/api/v1/srvs/?host=%d&name=%s", hostID, url.QueryEscape(serviceProtoName)), nil, http.StatusOK)
109109
if len(diags) > 0 {
110110
return diags
111111
}
@@ -139,7 +139,7 @@ func resourceSRVDelete(ctx context.Context, d *schema.ResourceData, m interface{
139139
}
140140

141141
// Delete the SRV record
142-
_, _, diags = httpRequest("DELETE", fmt.Sprintf("/api/v1/srvs/%d", srvId), nil, http.StatusNoContent, apiClient)
142+
_, _, diags = apiClient.httpRequest("DELETE", fmt.Sprintf("/api/v1/srvs/%d", srvId), nil, http.StatusNoContent)
143143
if len(diags) > 0 {
144144
return diags
145145
}

0 commit comments

Comments
 (0)