Skip to content

Commit

Permalink
Feature/add missing fields (#128)
Browse files Browse the repository at this point in the history
* fixing code warnings

* added 3 of the missing service fields

* adding missing fields on service

* implemented all missing fields on route except header

* implemented all missing fields on route

* implemented all missing fields

Co-authored-by: kevholditch <[email protected]>
  • Loading branch information
kevholditch-f3 and kevholditch authored Aug 9, 2021
1 parent f91a5a6 commit 6cda8f6
Show file tree
Hide file tree
Showing 18 changed files with 873 additions and 210 deletions.
6 changes: 5 additions & 1 deletion docs/resources/route.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ resource "kong_route" "route" {
preserve_host = true
regex_priority = 1
service_id = kong_service.service.id
header {
name = "x-test-1"
values = ["a", "b"]
}
}
```
Expand Down Expand Up @@ -52,7 +56,7 @@ resource "kong_route" "route" {
* `methods` - (Optional) A list of HTTP methods that match this Route
* `hosts` - (Optional) A list of domain names that match this Route
* `paths` - (Optional) A list of paths that match this Route
* `headers` - (Optional) One or more lists of values indexed by header name that will cause this Route to match if present in the request. The Host header cannot be used with this attribute: hosts should be specified using the hosts attribute.
* `header` - (Optional) One or more blocks of `name` to set name of header and `values` which is a list of `string` for the header values to match on. See above example of how to set. These headers will cause this Route to match if present in the request. The Host header cannot be used with this attribute: hosts should be specified using the hosts attribute.
* `https_redirect_status_code` - (Optional) The status code Kong responds with when all properties of a Route match except the protocol i.e. if the protocol of the request is HTTP instead of HTTPS. Location header is injected by Kong if the field is set to `301`, `302`, `307` or `308`. Accepted values are: `426`, `301`, `302`, `307`, `308`. Default: `426`.
* `strip_path` - (Optional) When matching a Route via one of the paths, strip the matching prefix from the upstream request URL. Default: true.
* `regex_priority` - (Optional) A number used to choose which route resolves a given request when several routes match it using regexes simultaneously.
Expand Down
48 changes: 45 additions & 3 deletions docs/resources/service.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,48 @@ resource "kong_service" "service" {
}
```

To use a client certificate and ca certificates combine with certificate resource (note protocol must be `https`):

```hcl
resource "kong_certificate" "certificate" {
certificate = <<EOF
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
EOF
private_key = <<EOF
-----BEGIN PRIVATE KEY-----
.....
-----END PRIVATE KEY-----
EOF
snis = ["foo.com"]
}
resource "kong_certificate" "ca" {
certificate = <<EOF
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
EOF
private_key = <<EOF
-----BEGIN PRIVATE KEY-----
.....
-----END PRIVATE KEY-----
EOF
snis = ["ca.com"]
}
resource "kong_service" "service" {
name = "test"
protocol = "https"
host = "test.org"
tls_verify = true
tls_verify_depth = 2
client_certificate_id = kong_certificate.certificate.id
ca_certificate_ids = [kong_certificate.ca.id]
}
```

## Argument reference

* `name` - (Required) Service name
Expand All @@ -30,10 +72,10 @@ resource "kong_service" "service" {
* `write_timeout` - (Optional, int) Write timout. Default(ms): 60000
* `read_timeout` - (Optional, int) Read timeout. Default(ms): 60000
* `tags` - (Optional) A list of strings associated with the Service for grouping and filtering.
* `client_certificate` - (Optional) Certificate to be used as client certificate while TLS handshaking to the upstream server.
* `tls_verify` - (Optional) Whether to enable verification of upstream server TLS certificate.
* `client_certificate_id` - (Optional) ID of Certificate to be used as client certificate while TLS handshaking to the upstream server. Use ID from `kong_certificate` resource
* `tls_verify` - (Optional) Whether to enable verification of upstream server TLS certificate. If not set then the nginx default is respected.
* `tls_verify_depth` - (Optional) Maximum depth of chain while verifying Upstream server’s TLS certificate.
* `ca_certificates` - (Optional) A of CA Certificate IDs (created from the certificate resource). that are used to build the trust store while verifying upstream server’s TLS certificate.
* `ca_certificate_ids` - (Optional) A of CA Certificate IDs (created from the certificate resource). that are used to build the trust store while verifying upstream server’s TLS certificate.


## Import
Expand Down
18 changes: 18 additions & 0 deletions docs/resources/upstream.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
## Example Usage

```hcl
resource "kong_certificate" "certificate" {
certificate = <<EOF
-----BEGIN CERTIFICATE-----
......
-----END CERTIFICATE-----
EOF
private_key = <<EOF
-----BEGIN PRIVATE KEY-----
.....
-----END PRIVATE KEY-----
EOF
snis = ["foo.com"]
}
resource "kong_upstream" "upstream" {
name = "sample_upstream"
slots = 10
Expand All @@ -12,6 +26,10 @@ resource "kong_upstream" "upstream" {
hash_fallback_header = "FallbackHeaderName"
hash_on_cookie = "CookieName"
hash_on_cookie_path = "/path"
host_header = "x-host"
tags = ["a", "b"]
client_certificate_id = kong_certificate.certificate.id
healthchecks {
active {
type = "https"
Expand Down
16 changes: 8 additions & 8 deletions kong/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,48 @@ type config struct {
func Provider() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"kong_admin_uri": &schema.Schema{
"kong_admin_uri": {
Type: schema.TypeString,
Required: true,
DefaultFunc: envDefaultFuncWithDefault("KONG_ADMIN_ADDR", "http://localhost:8001"),
Description: "The address of the kong admin url e.g. http://localhost:8001",
},
"kong_admin_username": &schema.Schema{
"kong_admin_username": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: envDefaultFuncWithDefault("KONG_ADMIN_USERNAME", ""),
Description: "An basic auth user for kong admin",
},
"kong_admin_password": &schema.Schema{
"kong_admin_password": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: envDefaultFuncWithDefault("KONG_ADMIN_PASSWORD", ""),
Description: "An basic auth password for kong admin",
},
"tls_skip_verify": &schema.Schema{
"tls_skip_verify": {
Type: schema.TypeBool,
Optional: true,
DefaultFunc: envDefaultFuncWithDefault("TLS_SKIP_VERIFY", "false"),
Description: "Whether to skip tls verify for https kong api endpoint using self signed or untrusted certs",
},
"kong_api_key": &schema.Schema{
"kong_api_key": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: envDefaultFuncWithDefault("KONG_API_KEY", ""),
Description: "API key for the kong api (if you have locked it down)",
},
"kong_admin_token": &schema.Schema{
"kong_admin_token": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: envDefaultFuncWithDefault("KONG_ADMIN_TOKEN", ""),
Description: "API key for the kong api (Enterprise Edition)",
},
"kong_workspace": &schema.Schema{
"kong_workspace": {
Type: schema.TypeString,
Optional: true,
Description: "Workspace context (Enterprise Edition)",
},
"strict_plugins_match": &schema.Schema{
"strict_plugins_match": {
Type: schema.TypeBool,
Optional: true,
ForceNew: false,
Expand Down
15 changes: 12 additions & 3 deletions kong/resource_kong_certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,24 @@ func resourceKongCertificateRead(ctx context.Context, d *schema.ResourceData, me
d.SetId("")
} else {
if certificate.Cert != nil {
d.Set("certificate", &certificate.Cert)
err := d.Set("certificate", &certificate.Cert)
if err != nil {
return diag.FromErr(err)
}
}

if certificate.Key != nil {
d.Set("private_key", &certificate.Key)
err := d.Set("private_key", &certificate.Key)
if err != nil {
return diag.FromErr(err)
}
}

if certificate.SNIs != nil {
d.Set("snis", StringValueSlice(certificate.SNIs))
err := d.Set("snis", StringValueSlice(certificate.SNIs))
if err != nil {
return diag.FromErr(err)
}
}
}

Expand Down
57 changes: 33 additions & 24 deletions kong/resource_kong_consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,29 @@ package kong
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"

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

func resourceKongConsumer() *schema.Resource {
return &schema.Resource{
Create: resourceKongConsumerCreate,
Read: resourceKongConsumerRead,
Delete: resourceKongConsumerDelete,
Update: resourceKongConsumerUpdate,
CreateContext: resourceKongConsumerCreate,
ReadContext: resourceKongConsumerRead,
DeleteContext: resourceKongConsumerDelete,
UpdateContext: resourceKongConsumerUpdate,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"username": &schema.Schema{
"username": {
Type: schema.TypeString,
Optional: true,
ForceNew: false,
},
"custom_id": &schema.Schema{
"custom_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: false,
Expand All @@ -33,26 +34,26 @@ func resourceKongConsumer() *schema.Resource {
}
}

func resourceKongConsumerCreate(d *schema.ResourceData, meta interface{}) error {
func resourceKongConsumerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {

consumerRequest := &kong.Consumer{
Username: kong.String(d.Get("username").(string)),
CustomID: kong.String(d.Get("custom_id").(string)),
}

client := meta.(*config).adminClient.Consumers
consumer, err := client.Create(context.Background(), consumerRequest)
consumer, err := client.Create(ctx, consumerRequest)

if err != nil {
return fmt.Errorf("failed to create kong consumer: %v error: %v", consumerRequest, err)
return diag.FromErr(fmt.Errorf("failed to create kong consumer: %v error: %v", consumerRequest, err))
}

d.SetId(*consumer.ID)

return resourceKongConsumerRead(d, meta)
return resourceKongConsumerRead(ctx, d, meta)
}

func resourceKongConsumerUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceKongConsumerUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
d.Partial(false)

consumerRequest := &kong.Consumer{
Expand All @@ -62,46 +63,54 @@ func resourceKongConsumerUpdate(d *schema.ResourceData, meta interface{}) error
}

client := meta.(*config).adminClient.Consumers
_, err := client.Update(context.Background(), consumerRequest)
_, err := client.Update(ctx, consumerRequest)

if err != nil {
return fmt.Errorf("error updating kong consumer: %s", err)
return diag.FromErr(fmt.Errorf("error updating kong consumer: %s", err))
}

return resourceKongConsumerRead(d, meta)
return resourceKongConsumerRead(ctx, d, meta)
}

func resourceKongConsumerRead(d *schema.ResourceData, meta interface{}) error {
func resourceKongConsumerRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {

var diags diag.Diagnostics
id := d.Id()

client := meta.(*config).adminClient.Consumers
consumer, err := client.Get(context.Background(), kong.String(id))
consumer, err := client.Get(ctx, kong.String(id))

if kong.IsNotFoundErr(err) {
d.SetId("")
} else if err != nil {
return fmt.Errorf("could not find kong consumer with id: %s error: %v", id, err)
return diag.FromErr(fmt.Errorf("could not find kong consumer with id: %s error: %v", id, err))
}

if consumer == nil {
d.SetId("")
} else {
d.Set("username", consumer.Username)
d.Set("custom_id", consumer.CustomID)
err := d.Set("username", consumer.Username)
if err != nil {
return diag.FromErr(err)
}
err = d.Set("custom_id", consumer.CustomID)
if err != nil {
return diag.FromErr(err)
}
}

return nil
return diags
}

func resourceKongConsumerDelete(d *schema.ResourceData, meta interface{}) error {
func resourceKongConsumerDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {

var diags diag.Diagnostics
client := meta.(*config).adminClient.Consumers
err := client.Delete(context.Background(), kong.String(d.Id()))
err := client.Delete(ctx, kong.String(d.Id()))

if err != nil {
return fmt.Errorf("could not delete kong consumer: %v", err)
return diag.FromErr(fmt.Errorf("could not delete kong consumer: %v", err))
}

return nil
return diags
}
21 changes: 15 additions & 6 deletions kong/resource_kong_consumer_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ func resourceKongConsumerACL() *schema.Resource {
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"consumer_id": &schema.Schema{
"consumer_id": {
Type: schema.TypeString,
Required: true,
ForceNew: false,
},
"group": &schema.Schema{
"group": {
Type: schema.TypeString,
Required: true,
ForceNew: false,
},
"tags": &schema.Schema{
"tags": {
Type: schema.TypeList,
Optional: true,
ForceNew: false,
Expand Down Expand Up @@ -98,9 +98,18 @@ func resourceKongConsumerACLRead(ctx context.Context, d *schema.ResourceData, me
if ACLGroup == nil {
d.SetId("")
} else {
d.Set("consumer_id", ACLGroup.Consumer.ID)
d.Set("group", ACLGroup.Group)
d.Set("tags", ACLGroup.Tags)
err := d.Set("consumer_id", ACLGroup.Consumer.ID)
if err != nil {
return diag.FromErr(err)
}
err = d.Set("group", ACLGroup.Group)
if err != nil {
return diag.FromErr(err)
}
err = d.Set("tags", ACLGroup.Tags)
if err != nil {
return diag.FromErr(err)
}
}

return diags
Expand Down
Loading

0 comments on commit 6cda8f6

Please sign in to comment.